authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-11-04 18:47:19-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-06 12:15:04-07:00
log3ba916584db5485c38ebf2390e8d22bc6d81bf8e
treecacae3c81235699d5271d2244cc1dfbe7f07be10
parent4e2a960b523070c7f8fddf0ea9b6e2a94e31dafe

actually remove stage1


491 files changed, 0 insertions(+), 124927 deletions(-)

deps/SoftFloat-3e-prebuilt/platform.h deleted-99
...@@ -1,99 +0,0 @@
1#ifndef ZIG_DEP_SOFTFLOAT_PLATFORM_H
2#define ZIG_DEP_SOFTFLOAT_PLATFORM_H
3
4#if defined(__BIG_ENDIAN__)
5#define BIGENDIAN 1
6#elif defined(_BIG_ENDIAN) && (_BIG_ENDIAN == 1)
7#define BIGENDIAN 1
8#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
9#define BIGENDIAN 1
10#elif defined(__ARMEB__)
11#define BIGENDIAN 1
12#elif defined(__THUMBEB__)
13#define BIGENDIAN 1
14#elif defined(__AARCH64EB__)
15#define BIGENDIAN 1
16#elif defined(_MIPSEB)
17#define BIGENDIAN 1
18#elif defined(__MIPSEB)
19#define BIGENDIAN 1
20#elif defined(__MIPSEB__)
21#define BIGENDIAN 1
22#elif defined(__sparc)
23#define BIGENDIAN 1
24#elif defined(__sparc__)
25#define BIGENDIAN 1
26#elif defined(_POWER)
27#define BIGENDIAN 1
28#elif defined(__hpux)
29#define BIGENDIAN 1
30#elif defined(__hppa)
31#define BIGENDIAN 1
32#elif defined(_POWER)
33#define BIGENDIAN 1
34#elif defined(__s390__)
35#define BIGENDIAN 1
36#endif
37
38#if defined(__LITTLE_ENDIAN__)
39#define LITTLEENDIAN 1
40#elif defined(_LITTLE_ENDIAN) && (_LITTLE_ENDIAN == 1)
41#define LITTLEENDIAN 1
42#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
43#define LITTLEENDIAN 1
44#elif defined(__ARMEL__)
45#define LITTLEENDIAN 1
46#elif defined(__THUMBEL__)
47#define LITTLEENDIAN 1
48#elif defined(__AARCH64EL__)
49#define LITTLEENDIAN 1
50#elif defined(_MIPSEL)
51#define LITTLEENDIAN 1
52#elif defined(__MIPSEL)
53#define LITTLEENDIAN 1
54#elif defined(__MIPSEL__)
55#define LITTLEENDIAN 1
56#elif defined(__i386__)
57#define LITTLEENDIAN 1
58#elif defined(__alpha__)
59#define LITTLEENDIAN 1
60#elif defined(__ia64)
61#define LITTLEENDIAN 1
62#elif defined(__ia64__)
63#define LITTLEENDIAN 1
64#elif defined(_M_IX86)
65#define LITTLEENDIAN 1
66#elif defined(_M_IA64)
67#define LITTLEENDIAN 1
68#elif defined(_M_ALPHA)
69#define LITTLEENDIAN 1
70#elif defined(__amd64)
71#define LITTLEENDIAN 1
72#elif defined(__amd64__)
73#define LITTLEENDIAN 1
74#elif defined(_M_AMD64)
75#define LITTLEENDIAN 1
76#elif defined(__x86_64)
77#define LITTLEENDIAN 1
78#elif defined(__x86_64__)
79#define LITTLEENDIAN 1
80#elif defined(_M_X64)
81#define LITTLEENDIAN 1
82#elif defined(__bfin__)
83#define LITTLEENDIAN 1
84#endif
85
86#if defined(LITTLEENDIAN) && defined(BIGENDIAN)
87#error unable to detect endianness
88#elif !defined(LITTLEENDIAN) && !defined(BIGENDIAN)
89#error unable to detect endianness
90#endif
91
92#define INLINE inline
93#if _MSC_VER
94#define THREAD_LOCAL __declspec(thread)
95#else
96#define THREAD_LOCAL __thread
97#endif
98
99#endif
deps/SoftFloat-3e/COPYING.txt deleted-37
...@@ -1,37 +0,0 @@
1
2License for Berkeley SoftFloat Release 3e
3
4John R. Hauser
52018 January 20
6
7The following applies to the whole of SoftFloat Release 3e as well as to
8each source file individually.
9
10Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the
11University of California. All rights reserved.
12
13Redistribution and use in source and binary forms, with or without
14modification, are permitted provided that the following conditions are met:
15
16 1. Redistributions of source code must retain the above copyright notice,
17 this list of conditions, and the following disclaimer.
18
19 2. Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions, and the following disclaimer in the
21 documentation and/or other materials provided with the distribution.
22
23 3. Neither the name of the University nor the names of its contributors
24 may be used to endorse or promote products derived from this software
25 without specific prior written permission.
26
27THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
28EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
30DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
31DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
34ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
deps/SoftFloat-3e/README.html deleted-49
...@@ -1,49 +0,0 @@
1
2<HTML>
3
4<HEAD>
5<TITLE>Berkeley SoftFloat Package Overview</TITLE>
6</HEAD>
7
8<BODY>
9
10<H1>Package Overview for Berkeley SoftFloat Release 3e</H1>
11
12<P>
13John R. Hauser<BR>
142018 January 20<BR>
15</P>
16
17<P>
18Berkeley SoftFloat is a software implementation of binary floating-point that
19conforms to the IEEE Standard for Floating-Point Arithmetic.
20SoftFloat is distributed in the form of C source code.
21Building the SoftFloat sources generates a library file (typically
22<CODE>softfloat.a</CODE> or <CODE>libsoftfloat.a</CODE>) containing the
23floating-point subroutines.
24</P>
25
26<P>
27The SoftFloat package is documented in the following files in the
28<CODE>doc</CODE> subdirectory:
29<BLOCKQUOTE>
30<TABLE>
31<TR>
32<TD><A HREF="doc/SoftFloat.html"><NOBR><CODE>SoftFloat.html</CODE></NOBR></A></TD>
33<TD>Documentation for using the SoftFloat functions.</TD>
34</TR>
35<TR>
36<TD><A HREF="doc/SoftFloat-source.html"><NOBR><CODE>SoftFloat-source.html</CODE></NOBR></A></TD>
37<TD>Documentation for building SoftFloat.</TD>
38</TR>
39<TR>
40<TD><A HREF="doc/SoftFloat-history.html"><NOBR><CODE>SoftFloat-history.html</CODE></A><CODE>&nbsp;&nbsp;&nbsp;</CODE></NOBR></TD>
41<TD>History of the major changes to SoftFloat.</TD>
42</TR>
43</TABLE>
44</BLOCKQUOTE>
45Other files in the package comprise the source code for SoftFloat.
46</P>
47
48</BODY>
49
deps/SoftFloat-3e/README.txt deleted-21
...@@ -1,21 +0,0 @@
1
2Package Overview for Berkeley SoftFloat Release 3e
3
4John R. Hauser
52018 January 20
6
7Berkeley SoftFloat is a software implementation of binary floating-point
8that conforms to the IEEE Standard for Floating-Point Arithmetic. SoftFloat
9is distributed in the form of C source code. Building the SoftFloat sources
10generates a library file (typically "softfloat.a" or "libsoftfloat.a")
11containing the floating-point subroutines.
12
13The SoftFloat package is documented in the following files in the "doc"
14subdirectory:
15
16 SoftFloat.html Documentation for using the SoftFloat functions.
17 SoftFloat-source.html Documentation for building SoftFloat.
18 SoftFloat-history.html History of the major changes to SoftFloat.
19
20Other files in the package comprise the source code for SoftFloat.
21
deps/SoftFloat-3e/doc/SoftFloat-history.html deleted-258
...@@ -1,258 +0,0 @@
1
2<HTML>
3
4<HEAD>
5<TITLE>Berkeley SoftFloat History</TITLE>
6</HEAD>
7
8<BODY>
9
10<H1>History of Berkeley SoftFloat, to Release 3e</H1>
11
12<P>
13John R. Hauser<BR>
142018 January 20<BR>
15</P>
16
17
18<H3>Release 3e (2018 January)</H3>
19
20<UL>
21
22<LI>
23Changed the default numeric code for optional rounding mode <CODE>odd</CODE>
24(round to odd, also known as <EM>jamming</EM>) from 5 to 6.
25
26<LI>
27Modified the behavior of rounding mode <CODE>odd</CODE> when rounding to an
28integer value (either conversion to an integer format or a
29&lsquo;<CODE>roundToInt</CODE>&rsquo; function).
30Previously, for those cases only, rounding mode <CODE>odd</CODE> acted the same
31as rounding to minimum magnitude.
32Now all operations are rounded consistently.
33
34<LI>
35Fixed some errors in the specialization code modeling Intel x86 floating-point,
36specifically the integers returned on invalid operations and the propagation of
37NaN payloads in a few rare cases.
38
39<LI>
40Added specialization code modeling ARM floating-point, conforming to VFPv2 or
41later.
42
43<LI>
44Added an example target for ARM processors.
45
46<LI>
47Fixed a minor bug whereby function <CODE>f16_to_ui64</CODE> might return a
48different integer than expected in the case that the floating-point operand is
49negative.
50
51<LI>
52Added example target-specific optimization for GCC, employing GCC instrinsics
53and support for <NOBR>128-bit</NOBR> integer arithmetic.
54
55<LI>
56Made other minor improvements.
57
58</UL>
59
60
61<H3>Release 3d (2017 August)</H3>
62
63<UL>
64
65<LI>
66Fixed bugs in the square root functions for <NOBR>64-bit</NOBR>
67double-precision, <NOBR>80-bit</NOBR> double-extended-precision, and
68<NOBR>128-bit</NOBR> quadruple-precision.
69For <NOBR>64-bit</NOBR> double-precision (<CODE>f64_sqrt</CODE>), the result
70could sometimes be off by <NOBR>1 unit</NOBR> in the last place
71(<NOBR>1 ulp</NOBR>) from what it should be.
72For the larger formats, the square root could be wrong in a large portion of
73the less-significant bits.
74(A bug in <CODE>f128_sqrt</CODE> was first reported by Alexei Sibidanov.)
75
76</UL>
77
78
79<H3>Release 3c (2017 February)</H3>
80
81<UL>
82
83<LI>
84Added optional rounding mode <CODE>odd</CODE> (round to odd, also known as
85<EM>jamming</EM>).
86
87<LI>
88Corrected the documentation concerning non-canonical representations in
89<NOBR>80-bit</NOBR> double-extended-precision.
90
91</UL>
92
93
94<H3>Release 3b (2016 July)</H3>
95
96<UL>
97
98<LI>
99Implemented the common <NOBR>16-bit</NOBR> &ldquo;half-precision&rdquo;
100floating-point format (<CODE>float16_t</CODE>).
101
102<LI>
103Made the integer values returned on invalid conversions to integer formats
104be determined by the port-specific specialization instead of being the same for
105all ports.
106
107<LI>
108Added preprocessor macro <CODE>THREAD_LOCAL</CODE> to allow the floating-point
109state (modes and exception flags) to be made per-thread.
110
111<LI>
112Modified the provided Makefiles to allow some options to be overridden from the
113<CODE>make</CODE> command.
114
115<LI>
116Made other minor improvements.
117
118</UL>
119
120
121<H3>Release 3a (2015 October)</H3>
122
123<UL>
124
125<LI>
126Replaced the license text supplied by the University of California, Berkeley.
127
128</UL>
129
130
131<H3>Release 3 (2015 February)</H3>
132
133<UL>
134
135<LI>
136Complete rewrite, funded by the University of California, Berkeley, and
137consequently having a different use license than earlier releases.
138Major changes included renaming most types and functions, upgrading some
139algorithms, restructuring the source files, and making SoftFloat into a true
140library.
141
142<LI>
143Added functions to convert between floating-point and unsigned integers, both
144<NOBR>32-bit</NOBR> and <NOBR>64-bit</NOBR> (<CODE>uint32_t</CODE> and
145<CODE>uint64_t</CODE>).
146
147<LI>
148Added functions for fused multiply-add, for all supported floating-point
149formats except <NOBR>80-bit</NOBR> double-extended-precision.
150
151<LI>
152Added support for a fifth rounding mode, <CODE>near_maxMag</CODE> (round to
153nearest, with ties to maximum magnitude, away from zero).
154
155<LI>
156Dropped the <CODE>timesoftfloat</CODE> program (now part of the Berkeley
157TestFloat package).
158
159</UL>
160
161
162<H3>Release 2c (2015 January)</H3>
163
164<UL>
165
166<LI>
167Fixed mistakes affecting some <NOBR>64-bit</NOBR> processors.
168
169<LI>
170Further improved the documentation and the wording for the legal restrictions
171on using SoftFloat releases <NOBR>through 2c</NOBR> (not applicable to
172<NOBR>Release 3</NOBR> or later).
173
174</UL>
175
176
177<H3>Release 2b (2002 May)</H3>
178
179<UL>
180
181<LI>
182Made minor updates to the documentation, including improved wording for the
183legal restrictions on using SoftFloat.
184
185</UL>
186
187
188<H3>Release 2a (1998 December)</H3>
189
190<UL>
191
192<LI>
193Added functions to convert between <NOBR>64-bit</NOBR> integers
194(<CODE>int64</CODE>) and all supported floating-point formats.
195
196<LI>
197Fixed a bug in all <NOBR>64-bit</NOBR>-version square root functions except
198<CODE>float32_sqrt</CODE> that caused the result sometimes to be off by
199<NOBR>1 unit</NOBR> in the last place (<NOBR>1 ulp</NOBR>) from what it should
200be.
201(Bug discovered by Paul Donahue.)
202
203<LI>
204Improved the Makefiles.
205</UL>
206
207
208<H3>Release 2 (1997 June)</H3>
209
210<UL>
211
212<LI>
213Created the <NOBR>64-bit</NOBR> (<CODE>bits64</CODE>) version, adding the
214<CODE>floatx80</CODE> and <CODE>float128</CODE> formats.
215
216<LI>
217Changed the source directory structure, splitting the sources into a
218<CODE>bits32</CODE> and a <CODE>bits64</CODE> version.
219Renamed <CODE>environment.h</CODE> to <CODE>milieu.h</CODE> to avoid confusion
220with environment variables.
221
222<LI>
223Fixed a small error that caused <CODE>float64_round_to_int</CODE> often to
224round the wrong way in nearest/even mode when the operand was between
2252<SUP>20</SUP> and 2<SUP>21</SUP> and halfway between two integers.
226
227</UL>
228
229
230<H3>Release 1a (1996 July)</H3>
231
232<UL>
233
234<LI>
235Corrected a mistake that caused borderline underflow cases not to raise the
236underflow flag when they should have.
237(Problem reported by Doug Priest.)
238
239<LI>
240Added the <CODE>float_detect_tininess</CODE> variable to control whether
241tininess is detected before or after rounding.
242
243</UL>
244
245
246<H3>Release 1 (1996 July)</H3>
247
248<UL>
249
250<LI>
251Original release, based on work done for the International Computer Science
252Institute (ICSI) in Berkeley, California.
253
254</UL>
255
256
257</BODY>
258
deps/SoftFloat-3e/doc/SoftFloat-source.html deleted-686
...@@ -1,686 +0,0 @@
1
2<HTML>
3
4<HEAD>
5<TITLE>Berkeley SoftFloat Source Documentation</TITLE>
6</HEAD>
7
8<BODY>
9
10<H1>Berkeley SoftFloat Release 3e: Source Documentation</H1>
11
12<P>
13John R. Hauser<BR>
142018 January 20<BR>
15</P>
16
17
18<H2>Contents</H2>
19
20<BLOCKQUOTE>
21<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0>
22<COL WIDTH=25>
23<COL WIDTH=*>
24<TR><TD COLSPAN=2>1. Introduction</TD></TR>
25<TR><TD COLSPAN=2>2. Limitations</TD></TR>
26<TR><TD COLSPAN=2>3. Acknowledgments and License</TD></TR>
27<TR><TD COLSPAN=2>4. SoftFloat Package Directory Structure</TD></TR>
28<TR><TD COLSPAN=2>5. Issues for Porting SoftFloat to a New Target</TD></TR>
29<TR>
30 <TD></TD>
31 <TD>5.1. Standard Headers <CODE>&lt;stdbool.h&gt;</CODE> and
32 <CODE>&lt;stdint.h&gt;</CODE></TD>
33</TR>
34<TR><TD></TD><TD>5.2. Specializing Floating-Point Behavior</TD></TR>
35<TR><TD></TD><TD>5.3. Macros for Build Options</TD></TR>
36<TR><TD></TD><TD>5.4. Adapting a Template Target Directory</TD></TR>
37<TR>
38 <TD></TD><TD>5.5. Target-Specific Optimization of Primitive Functions</TD>
39</TR>
40<TR><TD COLSPAN=2>6. Testing SoftFloat</TD></TR>
41<TR>
42 <TD COLSPAN=2>7. Providing SoftFloat as a Common Library for Applications</TD>
43</TR>
44<TR><TD COLSPAN=2>8. Contact Information</TD></TR>
45</TABLE>
46</BLOCKQUOTE>
47
48
49<H2>1. Introduction</H2>
50
51<P>
52This document gives information needed for compiling and/or porting Berkeley
53SoftFloat, a library of C functions implementing binary floating-point
54conforming to the IEEE Standard for Floating-Point Arithmetic.
55For basic documentation about SoftFloat refer to
56<A HREF="SoftFloat.html"><NOBR><CODE>SoftFloat.html</CODE></NOBR></A>.
57</P>
58
59<P>
60The source code for SoftFloat is intended to be relatively machine-independent
61and should be compilable with any ISO-Standard C compiler that also supports
62<NOBR>64-bit</NOBR> integers.
63SoftFloat has been successfully compiled with the GNU C Compiler
64(<CODE>gcc</CODE>) for several platforms.
65</P>
66
67<P>
68<NOBR>Release 3</NOBR> of SoftFloat was a complete rewrite relative to
69<NOBR>Release 2</NOBR> or earlier.
70Changes to the interface of SoftFloat functions are documented in
71<A HREF="SoftFloat.html"><NOBR><CODE>SoftFloat.html</CODE></NOBR></A>.
72The current version of SoftFloat is <NOBR>Release 3e</NOBR>.
73</P>
74
75
76<H2>2. Limitations</H2>
77
78<P>
79SoftFloat assumes the computer has an addressable byte size of either 8 or
80<NOBR>16 bits</NOBR>.
81(Nearly all computers in use today have <NOBR>8-bit</NOBR> bytes.)
82</P>
83
84<P>
85SoftFloat is written in C and is designed to work with other C code.
86The C compiler used must conform at a minimum to the 1989 ANSI standard for the
87C language (same as the 1990 ISO standard) and must in addition support basic
88arithmetic on <NOBR>64-bit</NOBR> integers.
89Earlier releases of SoftFloat included implementations of <NOBR>32-bit</NOBR>
90single-precision and <NOBR>64-bit</NOBR> double-precision floating-point that
91did not require <NOBR>64-bit</NOBR> integers, but this option is not supported
92starting with <NOBR>Release 3</NOBR>.
93Since 1999, ISO standards for C have mandated compiler support for
94<NOBR>64-bit</NOBR> integers.
95A compiler conforming to the 1999 C Standard or later is recommended but not
96strictly required.
97</P>
98
99<P>
100<NOBR>C Standard</NOBR> header files <CODE>&lt;stdbool.h&gt;</CODE> and
101<CODE>&lt;stdint.h&gt;</CODE> are required for defining standard Boolean and
102integer types.
103If these headers are not supplied with the C compiler, minimal substitutes must
104be provided.
105SoftFloat&rsquo;s dependence on these headers is detailed later in
106<NOBR>section 5.1</NOBR>, <I>Standard Headers <CODE>&lt;stdbool.h&gt;</CODE>
107and <CODE>&lt;stdint.h&gt;</CODE></I>.
108</P>
109
110
111<H2>3. Acknowledgments and License</H2>
112
113<P>
114The SoftFloat package was written by me, <NOBR>John R.</NOBR> Hauser.
115<NOBR>Release 3</NOBR> of SoftFloat was a completely new implementation
116supplanting earlier releases.
117The project to create <NOBR>Release 3</NOBR> (now <NOBR>through 3e</NOBR>) was
118done in the employ of the University of California, Berkeley, within the
119Department of Electrical Engineering and Computer Sciences, first for the
120Parallel Computing Laboratory (Par Lab) and then for the ASPIRE Lab.
121The work was officially overseen by Prof. Krste Asanovic, with funding provided
122by these sources:
123<BLOCKQUOTE>
124<TABLE>
125<COL>
126<COL WIDTH=10>
127<COL>
128<TR>
129<TD VALIGN=TOP><NOBR>Par Lab:</NOBR></TD>
130<TD></TD>
131<TD>
132Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery
133(Award #DIG07-10227), with additional support from Par Lab affiliates Nokia,
134NVIDIA, Oracle, and Samsung.
135</TD>
136</TR>
137<TR>
138<TD VALIGN=TOP><NOBR>ASPIRE Lab:</NOBR></TD>
139<TD></TD>
140<TD>
141DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from
142ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA,
143Oracle, and Samsung.
144</TD>
145</TR>
146</TABLE>
147</BLOCKQUOTE>
148</P>
149
150<P>
151The following applies to the whole of SoftFloat <NOBR>Release 3e</NOBR> as well
152as to each source file individually.
153</P>
154
155<P>
156Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the
157University of California.
158All rights reserved.
159</P>
160
161<P>
162Redistribution and use in source and binary forms, with or without
163modification, are permitted provided that the following conditions are met:
164<OL>
165
166<LI>
167<P>
168Redistributions of source code must retain the above copyright notice, this
169list of conditions, and the following disclaimer.
170</P>
171
172<LI>
173<P>
174Redistributions in binary form must reproduce the above copyright notice, this
175list of conditions, and the following disclaimer in the documentation and/or
176other materials provided with the distribution.
177</P>
178
179<LI>
180<P>
181Neither the name of the University nor the names of its contributors may be
182used to endorse or promote products derived from this software without specific
183prior written permission.
184</P>
185
186</OL>
187</P>
188
189<P>
190THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS &ldquo;AS IS&rdquo;,
191AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
192IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
193DISCLAIMED.
194IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
195INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
196BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
197DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
198LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
199OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
200ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
201</P>
202
203
204<H2>4. SoftFloat Package Directory Structure</H2>
205
206<P>
207Because SoftFloat is targeted to multiple platforms, its source code is
208slightly scattered between target-specific and target-independent directories
209and files.
210The supplied directory structure is as follows:
211<BLOCKQUOTE>
212<PRE>
213doc
214source
215 include
216 8086
217 8086-SSE
218 ARM-VFPv2
219 ARM-VFPv2-defaultNaN
220build
221 template-FAST_INT64
222 template-not-FAST_INT64
223 Linux-386-GCC
224 Linux-386-SSE2-GCC
225 Linux-x86_64-GCC
226 Linux-ARM-VFPv2-GCC
227 Win32-MinGW
228 Win32-SSE2-MinGW
229 Win64-MinGW-w64
230</PRE>
231</BLOCKQUOTE>
232The majority of the SoftFloat sources are provided in the <CODE>source</CODE>
233directory.
234The <CODE>include</CODE> subdirectory contains several header files
235(unsurprisingly), while the other subdirectories of <CODE>source</CODE> contain
236source files that specialize the floating-point behavior to match particular
237processor families:
238<BLOCKQUOTE>
239<DL>
240<DT><CODE>8086</CODE></DT>
241<DD>
242Intel&rsquo;s older, 8087-derived floating-point, extended to all supported
243floating-point types
244</DD>
245<DT><CODE>8086-SSE</CODE></DT>
246<DD>
247Intel&rsquo;s x86 processors with Streaming SIMD Extensions (SSE) and later
248compatible extensions, having 8087 behavior for <NOBR>80-bit</NOBR>
249double-extended-precision (<CODE>extFloat80_t</CODE>) and SSE behavior for
250other floating-point types
251</DD>
252<DT><CODE>ARM-VFPv2</CODE></DT>
253<DD>
254ARM&rsquo;s VFPv2 or later floating-point, with NaN payload propagation
255</DD>
256<DT><CODE>ARM-VFPv2-defaultNaN</CODE></DT>
257<DD>
258ARM&rsquo;s VFPv2 or later floating-point, with the &ldquo;default NaN&rdquo;
259option
260</DD>
261</DL>
262</BLOCKQUOTE>
263If other specializations are attempted, these would be expected to be other
264subdirectories of <CODE>source</CODE> alongside the ones listed above.
265Specialization is covered later, in <NOBR>section 5.2</NOBR>, <I>Specializing
266Floating-Point Behavior</I>.
267</P>
268
269<P>
270The <CODE>build</CODE> directory is intended to contain a subdirectory for each
271target platform for which a build of the SoftFloat library may be created.
272For each build target, the target&rsquo;s subdirectory is where all derived
273object files and the completed SoftFloat library (typically
274<CODE>softfloat.a</CODE> or <CODE>libsoftfloat.a</CODE>) are created.
275The two <CODE>template</CODE> subdirectories are not actual build targets but
276contain sample files for creating new target directories.
277(The meaning of <CODE>FAST_INT64</CODE> will be explained later.)
278</P>
279
280<P>
281Ignoring the <CODE>template</CODE> directories, the supplied target directories
282are intended to follow a naming system of
283<NOBR><CODE>&lt;<I>execution-environment</I>&gt;-&lt;<I>compiler</I>&gt;</CODE></NOBR>.
284For the example targets,
285<NOBR><CODE>&lt;<I>execution-environment</I>&gt;</CODE></NOBR> is
286<NOBR><CODE>Linux-386</CODE></NOBR>, <NOBR><CODE>Linux-386-SSE2</CODE></NOBR>,
287<NOBR><CODE>Linux-x86_64</CODE></NOBR>,
288<NOBR><CODE>Linux-ARM-VFPv2</CODE></NOBR>, <CODE>Win32</CODE>,
289<NOBR><CODE>Win32-SSE2</CODE></NOBR>, or <CODE>Win64</CODE>, and
290<NOBR><CODE>&lt;<I>compiler</I>&gt;</CODE></NOBR> is <CODE>GCC</CODE>,
291<CODE>MinGW</CODE>, or <NOBR><CODE>MinGW-w64</CODE></NOBR>.
292</P>
293
294<P>
295All of the supplied target directories are merely examples that may or may not
296be correct for compiling on any particular system.
297Despite requests, there are currently no plans to include and maintain in the
298SoftFloat package the build files needed for a great many users&rsquo;
299compilation environments, which can span a huge range of operating systems,
300compilers, and other tools.
301</P>
302
303<P>
304As supplied, each target directory contains two files:
305<BLOCKQUOTE>
306<PRE>
307Makefile
308platform.h
309</PRE>
310</BLOCKQUOTE>
311The provided <CODE>Makefile</CODE> is written for GNU <CODE>make</CODE>.
312A build of SoftFloat for the specific target is begun by executing the
313<CODE>make</CODE> command with the target directory as the current directory.
314A completely different build tool can be used if an appropriate
315<CODE>Makefile</CODE> equivalent is created.
316</P>
317
318<P>
319The <CODE>platform.h</CODE> header file exists to provide a location for
320additional C declarations specific to the build target.
321Every C source file of SoftFloat contains a <CODE>#include</CODE> for
322<CODE>platform.h</CODE>.
323In many cases, the contents of <CODE>platform.h</CODE> can be as simple as one
324or two lines of code.
325At the other extreme, to get maximal performance from SoftFloat, it may be
326desirable to include in header <CODE>platform.h</CODE> (directly or via
327<CODE>#include</CODE>) declarations for numerous target-specific optimizations.
328Such possibilities are discussed in the next section, <I>Issues for Porting
329SoftFloat to a New Target</I>.
330If the target&rsquo;s compiler or library has bugs or other shortcomings,
331workarounds for these issues may also be possible with target-specific
332declarations in <CODE>platform.h</CODE>, avoiding the need to modify the main
333SoftFloat sources.
334</P>
335
336
337<H2>5. Issues for Porting SoftFloat to a New Target</H2>
338
339<H3>5.1. Standard Headers <CODE>&lt;stdbool.h&gt;</CODE> and <CODE>&lt;stdint.h&gt;</CODE></H3>
340
341<P>
342The SoftFloat sources make use of standard headers
343<CODE>&lt;stdbool.h&gt;</CODE> and <CODE>&lt;stdint.h&gt;</CODE>, which have
344been part of the ISO C Standard Library since 1999.
345With any recent compiler, these standard headers are likely to be supported,
346even if the compiler does not claim complete conformance to the latest ISO C
347Standard.
348For older or nonstandard compilers, substitutes for
349<CODE>&lt;stdbool.h&gt;</CODE> and <CODE>&lt;stdint.h&gt;</CODE> may need to be
350created.
351SoftFloat depends on these names from <CODE>&lt;stdbool.h&gt;</CODE>:
352<BLOCKQUOTE>
353<PRE>
354bool
355true
356false
357</PRE>
358</BLOCKQUOTE>
359and on these names from <CODE>&lt;stdint.h&gt;</CODE>:
360<BLOCKQUOTE>
361<PRE>
362uint16_t
363uint32_t
364uint64_t
365int32_t
366int64_t
367UINT64_C
368INT64_C
369uint_least8_t
370uint_fast8_t
371uint_fast16_t
372uint_fast32_t
373uint_fast64_t
374int_fast8_t
375int_fast16_t
376int_fast32_t
377int_fast64_t
378</PRE>
379</BLOCKQUOTE>
380</P>
381
382
383<H3>5.2. Specializing Floating-Point Behavior</H3>
384
385<P>
386The IEEE Floating-Point Standard allows for some flexibility in a conforming
387implementation, particularly concerning NaNs.
388The SoftFloat <CODE>source</CODE> directory is supplied with some
389<I>specialization</I> subdirectories containing possible definitions for this
390implementation-specific behavior.
391For example, the <CODE>8086</CODE> and <NOBR><CODE>8086-SSE</CODE></NOBR>
392subdirectories have source files that specialize SoftFloat&rsquo;s behavior to
393match that of Intel&rsquo;s x86 line of processors.
394The files in a specialization subdirectory must determine:
395<UL>
396<LI>
397whether tininess for underflow is detected before or after rounding by default;
398<LI>
399how signaling NaNs are distinguished from quiet NaNs;
400<LI>
401what (if anything) special happens when exceptions are raised;
402<LI>
403the default generated quiet NaNs;
404<LI>
405how NaNs are propagated from function inputs to output; and
406<LI>
407the integer results returned when conversions to integer type raise the
408<I>invalid</I> exception.
409</UL>
410</P>
411
412<P>
413As provided, the build process for a target expects to involve exactly
414<EM>one</EM> specialization directory that defines <EM>all</EM> of these
415implementation-specific details for the target.
416A specialization directory such as <CODE>8086</CODE> is expected to contain a
417header file called <CODE>specialize.h</CODE>, together with whatever other
418source files are needed to complete the specialization.
419</P>
420
421<P>
422A new build target may use an existing specialization, such as the ones
423provided by the <CODE>8086</CODE> and <NOBR><CODE>8086-SSE</CODE></NOBR>
424subdirectories.
425If a build target needs a new specialization, different from any existing ones,
426it is recommended that a new specialization directory be created for this
427purpose.
428The <CODE>specialize.h</CODE> header file from any of the provided
429specialization subdirectories can be used as a model for what definitions are
430needed.
431</P>
432
433
434<H3>5.3. Macros for Build Options</H3>
435
436<P>
437The SoftFloat source files adapt the floating-point implementation according to
438several C preprocessor macros:
439<BLOCKQUOTE>
440<DL>
441<DT><CODE>LITTLEENDIAN</CODE>
442<DD>
443Must be defined for little-endian machines; must not be defined for big-endian
444machines.
445<DT><CODE>INLINE</CODE>
446<DD>
447Specifies the sequence of tokens used to indicate that a C function should be
448inlined.
449If macro <CODE>INLINE_LEVEL</CODE> is defined with a value of 1 or higher, this
450macro must be defined; otherwise, this macro is ignored and need not be
451defined.
452For compilers that conform to the C Standard&rsquo;s rules for inline
453functions, this macro can be defined as the single keyword <CODE>inline</CODE>.
454For other compilers that follow a convention pre-dating the standardization of
455<CODE>inline</CODE>, this macro may need to be defined to <CODE>extern</CODE>
456<CODE>inline</CODE>.
457<DT><CODE>THREAD_LOCAL</CODE>
458<DD>
459Can be defined to a sequence of tokens that, when appearing at the start of a
460variable declaration, indicates to the C compiler that the variable is
461<I>per-thread</I>, meaning that each execution thread gets its own separate
462instance of the variable.
463This macro is used in header <CODE>softfloat.h</CODE> in the declarations of
464variables <CODE>softfloat_roundingMode</CODE>,
465<CODE>softfloat_detectTininess</CODE>, <CODE>extF80_roundingPrecision</CODE>,
466and <CODE>softfloat_exceptionFlags</CODE>.
467If macro <CODE>THREAD_LOCAL</CODE> is left undefined, these variables will
468default to being ordinary global variables.
469Depending on the compiler, possible valid definitions of this macro include
470<CODE>_Thread_local</CODE> and <CODE>__thread</CODE>.
471</DL>
472<DL>
473<DT><CODE>SOFTFLOAT_ROUND_ODD</CODE>
474<DD>
475Can be defined to enable support for optional rounding mode
476<CODE>softfloat_round_odd</CODE>.
477</DL>
478<DL>
479<DT><CODE>INLINE_LEVEL</CODE>
480<DD>
481Can be defined to an integer to determine the degree of inlining requested of
482the compiler.
483Larger numbers request that more inlining be done.
484If this macro is not defined or is defined to a value less <NOBR>than 1</NOBR>
485(zero or negative), no inlining is requested.
486The maximum effective value is no higher <NOBR>than 5</NOBR>.
487Defining this macro to a value greater than 5 is the same as defining it
488<NOBR>to 5</NOBR>.
489<DT><CODE>SOFTFLOAT_FAST_INT64</CODE>
490<DD>
491Can be defined to indicate that the build target&rsquo;s implementation of
492<NOBR>64-bit</NOBR> arithmetic is efficient.
493For newer <NOBR>64-bit</NOBR> processors, this macro should usually be defined.
494For very small microprocessors whose buses and registers are <NOBR>8-bit</NOBR>
495or <NOBR>16-bit</NOBR> in size, this macro should usually not be defined.
496Whether this macro should be defined for a <NOBR>32-bit</NOBR> processor may
497depend on the target machine and the applications that will use SoftFloat.
498<DT><CODE>SOFTFLOAT_FAST_DIV32TO16</CODE>
499<DD>
500Can be defined to indicate that the target&rsquo;s division operator
501<NOBR>in C</NOBR> (written as <CODE>/</CODE>) is reasonably efficient for
502dividing a <NOBR>32-bit</NOBR> unsigned integer by a <NOBR>16-bit</NOBR>
503unsigned integer.
504Setting this macro may affect the performance of function <CODE>f16_div</CODE>.
505<DT><CODE>SOFTFLOAT_FAST_DIV64TO32</CODE>
506<DD>
507Can be defined to indicate that the target&rsquo;s division operator
508<NOBR>in C</NOBR> (written as <CODE>/</CODE>) is reasonably efficient for
509dividing a <NOBR>64-bit</NOBR> unsigned integer by a <NOBR>32-bit</NOBR>
510unsigned integer.
511Setting this macro may affect the performance of division, remainder, and
512square root operations other than <CODE>f16_div</CODE>.
513</DL>
514</BLOCKQUOTE>
515</P>
516
517<P>
518Following the usual custom <NOBR>for C</NOBR>, for most of these macros (all
519except <CODE>INLINE</CODE>, <CODE>THREAD_LOCAL</CODE>, and
520<CODE>INLINE_LEVEL</CODE>), the content of any definition is irrelevant;
521what matters is a macro&rsquo;s effect on <CODE>#ifdef</CODE> directives.
522</P>
523
524<P>
525It is recommended that any definitions of macros <CODE>LITTLEENDIAN</CODE>,
526<CODE>INLINE</CODE>, and <CODE>THREAD_LOCAL</CODE> be made in a build
527target&rsquo;s <CODE>platform.h</CODE> header file, because these macros are
528expected to be determined inflexibly by the target machine and compiler.
529The other five macros select options and control optimization, and thus might
530be better located in the target&rsquo;s Makefile (or its equivalent).
531</P>
532
533
534<H3>5.4. Adapting a Template Target Directory</H3>
535
536<P>
537In the <CODE>build</CODE> directory, two <CODE>template</CODE> subdirectories
538provide models for new target directories.
539Two different templates exist because different functions are needed in the
540SoftFloat library depending on whether macro <CODE>SOFTFLOAT_FAST_INT64</CODE>
541is defined.
542If macro <CODE>SOFTFLOAT_FAST_INT64</CODE> will be defined,
543<NOBR><CODE>template-FAST_INT64</CODE></NOBR> is the template to use;
544otherwise, <NOBR><CODE>template-not-FAST_INT64</CODE></NOBR> is the appropriate
545template.
546A new target directory can be created by copying the correct template directory
547and editing the files inside.
548To avoid confusion, it would be wise to refrain from editing the files within a
549template directory directly.
550</P>
551
552
553<H3>5.5. Target-Specific Optimization of Primitive Functions</H3>
554
555<P>
556Header file <CODE>primitives.h</CODE> (in directory
557<CODE>source/include</CODE>) declares macros and functions for numerous
558underlying arithmetic operations upon which many of SoftFloat&rsquo;s
559floating-point functions are ultimately built.
560The SoftFloat sources include implementations of all of these functions/macros,
561written as standard C code, so a complete and correct SoftFloat library can be
562created using only the supplied code for all functions.
563However, for many targets, SoftFloat&rsquo;s performance can be improved by
564substituting target-specific implementations of some of the functions/macros
565declared in <CODE>primitives.h</CODE>.
566</P>
567
568<P>
569For example, <CODE>primitives.h</CODE> declares a function called
570<CODE>softfloat_countLeadingZeros32</CODE> that takes an unsigned
571<NOBR>32-bit</NOBR> integer as an argument and returns the number of the
572integer&rsquo;s most-significant bits that are zeros.
573While the SoftFloat sources include an implementation of this function written
574in <NOBR>standard C</NOBR>, many processors can perform this same function
575directly in only one or two machine instructions.
576An alternative, target-specific implementation that maps to those instructions
577is likely to be more efficient than the generic C code from the SoftFloat
578package.
579</P>
580
581<P>
582A build target can replace the supplied version of any function or macro of
583<CODE>primitives.h</CODE> by defining a macro with the same name in the
584target&rsquo;s <CODE>platform.h</CODE> header file.
585For this purpose, it may be helpful for <CODE>platform.h</CODE> to
586<CODE>#include</CODE> header file <CODE>primitiveTypes.h</CODE>, which defines
587types used for arguments and results of functions declared in
588<CODE>primitives.h</CODE>.
589When a desired replacement implementation is a function, not a macro, it is
590sufficient for <CODE>platform.h</CODE> to include the line
591<BLOCKQUOTE>
592<PRE>
593#define &lt;<I>function-name</I>&gt; &lt;<I>function-name</I>&gt;
594</PRE>
595</BLOCKQUOTE>
596where <NOBR><CODE>&lt;<I>function-name</I>&gt;</CODE></NOBR> is the name of the
597function.
598This technically defines <NOBR><CODE>&lt;<I>function-name</I>&gt;</CODE></NOBR>
599as a macro, but one that resolves to the same name, which may then be a
600function.
601(A preprocessor that conforms to the C Standard is required to limit recursive
602macro expansion from being applied more than once.)
603</P>
604
605<P>
606The supplied header file <CODE>opts-GCC.h</CODE> (in directory
607<CODE>source/include</CODE>) provides an example of target-specific
608optimization for the GCC compiler.
609Each GCC target example in the <CODE>build</CODE> directory has
610<BLOCKQUOTE>
611<CODE>#include "opts-GCC.h"</CODE>
612</BLOCKQUOTE>
613in its <CODE>platform.h</CODE> header file.
614Before <CODE>opts-GCC.h</CODE> is included, the following macros must be
615defined (or not) to control which features are invoked:
616<BLOCKQUOTE>
617<DL>
618<DT><CODE>SOFTFLOAT_BUILTIN_CLZ</CODE></DT>
619<DD>
620If defined, SoftFloat&rsquo;s internal
621&lsquo;<CODE>countLeadingZeros</CODE>&rsquo; functions use intrinsics
622<CODE>__builtin_clz</CODE> and <CODE>__builtin_clzll</CODE>.
623</DD>
624<DT><CODE>SOFTFLOAT_INTRINSIC_INT128</CODE></DT>
625<DD>
626If defined, SoftFloat makes use of GCC&rsquo;s nonstandard <NOBR>128-bit</NOBR>
627integer type <CODE>__int128</CODE>.
628</DD>
629</DL>
630</BLOCKQUOTE>
631On some machines, these improvements are observed to increase the speeds of
632<CODE>f64_mul</CODE> and <CODE>f128_mul</CODE> by around 20 to 25%, although
633other functions receive less dramatic boosts, or none at all.
634Results can vary greatly across different platforms.
635</P>
636
637
638<H2>6. Testing SoftFloat</H2>
639
640<P>
641SoftFloat can be tested using the <CODE>testsoftfloat</CODE> program by the
642same author.
643This program is part of the Berkeley TestFloat package available at the Web
644page
645<A HREF="http://www.jhauser.us/arithmetic/TestFloat.html"><NOBR><CODE>http://www.jhauser.us/arithmetic/TestFloat.html</CODE></NOBR></A>.
646The TestFloat package also has a program called <CODE>timesoftfloat</CODE> that
647measures the speed of SoftFloat&rsquo;s floating-point functions.
648</P>
649
650
651<H2>7. Providing SoftFloat as a Common Library for Applications</H2>
652
653<P>
654Header file <CODE>softfloat.h</CODE> defines the SoftFloat interface as seen by
655clients.
656If the SoftFloat library will be made a common library for programs on a
657system, the supplied <CODE>softfloat.h</CODE> has a couple of deficiencies for
658this purpose:
659<UL>
660<LI>
661As supplied, <CODE>softfloat.h</CODE> depends on another header,
662<CODE>softfloat_types.h</CODE>, that is not intended for public use but which
663must also be visible to the programmer&rsquo;s compiler.
664<LI>
665More troubling, at the time <CODE>softfloat.h</CODE> is included in a C source
666file, macros <CODE>SOFTFLOAT_FAST_INT64</CODE> and <CODE>THREAD_LOCAL</CODE>
667must be defined, or not defined, consistent with how these macro were defined
668when the SoftFloat library was built.
669</UL>
670In the situation that new programs may regularly <CODE>#include</CODE> header
671file <CODE>softfloat.h</CODE>, it is recommended that a custom, self-contained
672version of this header file be created that eliminates these issues.
673</P>
674
675
676<H2>8. Contact Information</H2>
677
678<P>
679At the time of this writing, the most up-to-date information about SoftFloat
680and the latest release can be found at the Web page
681<A HREF="http://www.jhauser.us/arithmetic/SoftFloat.html"><NOBR><CODE>http://www.jhauser.us/arithmetic/SoftFloat.html</CODE></NOBR></A>.
682</P>
683
684
685</BODY>
686
deps/SoftFloat-3e/doc/SoftFloat.html deleted-1527
...@@ -1,1527 +0,0 @@
1
2<HTML>
3
4<HEAD>
5<TITLE>Berkeley SoftFloat Library Interface</TITLE>
6</HEAD>
7
8<BODY>
9
10<H1>Berkeley SoftFloat Release 3e: Library Interface</H1>
11
12<P>
13John R. Hauser<BR>
142018 January 20<BR>
15</P>
16
17
18<H2>Contents</H2>
19
20<BLOCKQUOTE>
21<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0>
22<COL WIDTH=25>
23<COL WIDTH=*>
24<TR><TD COLSPAN=2>1. Introduction</TD></TR>
25<TR><TD COLSPAN=2>2. Limitations</TD></TR>
26<TR><TD COLSPAN=2>3. Acknowledgments and License</TD></TR>
27<TR><TD COLSPAN=2>4. Types and Functions</TD></TR>
28<TR><TD></TD><TD>4.1. Boolean and Integer Types</TD></TR>
29<TR><TD></TD><TD>4.2. Floating-Point Types</TD></TR>
30<TR><TD></TD><TD>4.3. Supported Floating-Point Functions</TD></TR>
31<TR>
32 <TD></TD>
33 <TD>4.4. Non-canonical Representations in <CODE>extFloat80_t</CODE></TD>
34</TR>
35<TR><TD></TD><TD>4.5. Conventions for Passing Arguments and Results</TD></TR>
36<TR><TD COLSPAN=2>5. Reserved Names</TD></TR>
37<TR><TD COLSPAN=2>6. Mode Variables</TD></TR>
38<TR><TD></TD><TD>6.1. Rounding Mode</TD></TR>
39<TR><TD></TD><TD>6.2. Underflow Detection</TD></TR>
40<TR>
41 <TD></TD>
42 <TD>6.3. Rounding Precision for the <NOBR>80-Bit</NOBR> Extended Format</TD>
43</TR>
44<TR><TD COLSPAN=2>7. Exceptions and Exception Flags</TD></TR>
45<TR><TD COLSPAN=2>8. Function Details</TD></TR>
46<TR><TD></TD><TD>8.1. Conversions from Integer to Floating-Point</TD></TR>
47<TR><TD></TD><TD>8.2. Conversions from Floating-Point to Integer</TD></TR>
48<TR><TD></TD><TD>8.3. Conversions Among Floating-Point Types</TD></TR>
49<TR><TD></TD><TD>8.4. Basic Arithmetic Functions</TD></TR>
50<TR><TD></TD><TD>8.5. Fused Multiply-Add Functions</TD></TR>
51<TR><TD></TD><TD>8.6. Remainder Functions</TD></TR>
52<TR><TD></TD><TD>8.7. Round-to-Integer Functions</TD></TR>
53<TR><TD></TD><TD>8.8. Comparison Functions</TD></TR>
54<TR><TD></TD><TD>8.9. Signaling NaN Test Functions</TD></TR>
55<TR><TD></TD><TD>8.10. Raise-Exception Function</TD></TR>
56<TR><TD COLSPAN=2>9. Changes from SoftFloat <NOBR>Release 2</NOBR></TD></TR>
57<TR><TD></TD><TD>9.1. Name Changes</TD></TR>
58<TR><TD></TD><TD>9.2. Changes to Function Arguments</TD></TR>
59<TR><TD></TD><TD>9.3. Added Capabilities</TD></TR>
60<TR><TD></TD><TD>9.4. Better Compatibility with the C Language</TD></TR>
61<TR><TD></TD><TD>9.5. New Organization as a Library</TD></TR>
62<TR><TD></TD><TD>9.6. Optimization Gains (and Losses)</TD></TR>
63<TR><TD COLSPAN=2>10. Future Directions</TD></TR>
64<TR><TD COLSPAN=2>11. Contact Information</TD></TR>
65</TABLE>
66</BLOCKQUOTE>
67
68
69<H2>1. Introduction</H2>
70
71<P>
72Berkeley SoftFloat is a software implementation of binary floating-point that
73conforms to the IEEE Standard for Floating-Point Arithmetic.
74The current release supports five binary formats: <NOBR>16-bit</NOBR>
75half-precision, <NOBR>32-bit</NOBR> single-precision, <NOBR>64-bit</NOBR>
76double-precision, <NOBR>80-bit</NOBR> double-extended-precision, and
77<NOBR>128-bit</NOBR> quadruple-precision.
78The following functions are supported for each format:
79<UL>
80<LI>
81addition, subtraction, multiplication, division, and square root;
82<LI>
83fused multiply-add as defined by the IEEE Standard, except for
84<NOBR>80-bit</NOBR> double-extended-precision;
85<LI>
86remainder as defined by the IEEE Standard;
87<LI>
88round to integral value;
89<LI>
90comparisons;
91<LI>
92conversions to/from other supported formats; and
93<LI>
94conversions to/from <NOBR>32-bit</NOBR> and <NOBR>64-bit</NOBR> integers,
95signed and unsigned.
96</UL>
97All operations required by the original 1985 version of the IEEE Floating-Point
98Standard are implemented, except for conversions to and from decimal.
99</P>
100
101<P>
102This document gives information about the types defined and the routines
103implemented by SoftFloat.
104It does not attempt to define or explain the IEEE Floating-Point Standard.
105Information about the standard is available elsewhere.
106</P>
107
108<P>
109The current version of SoftFloat is <NOBR>Release 3e</NOBR>.
110This release modifies the behavior of the rarely used <I>odd</I> rounding mode
111(<I>round to odd</I>, also known as <I>jamming</I>), and also adds some new
112specialization and optimization examples for those compiling SoftFloat.
113</P>
114
115<P>
116The previous <NOBR>Release 3d</NOBR> fixed bugs that were found in the square
117root functions for the <NOBR>64-bit</NOBR>, <NOBR>80-bit</NOBR>, and
118<NOBR>128-bit</NOBR> floating-point formats.
119(Thanks to Alexei Sibidanov at the University of Victoria for reporting an
120incorrect result.)
121The bugs affected all prior <NOBR>Release-3</NOBR> versions of SoftFloat
122<NOBR>through 3c</NOBR>.
123The flaw in the <NOBR>64-bit</NOBR> floating-point square root function was of
124very minor impact, causing a <NOBR>1-ulp</NOBR> error (<NOBR>1 unit</NOBR> in
125the last place) a few times out of a billion.
126The bugs in the <NOBR>80-bit</NOBR> and <NOBR>128-bit</NOBR> square root
127functions were more serious.
128Although incorrect results again occurred only a few times out of a billion,
129when they did occur a large portion of the less-significant bits could be
130wrong.
131</P>
132
133<P>
134Among earlier releases, 3b was notable for adding support for the
135<NOBR>16-bit</NOBR> half-precision format.
136For more about the evolution of SoftFloat releases, see
137<A HREF="SoftFloat-history.html"><NOBR><CODE>SoftFloat-history.html</CODE></NOBR></A>.
138</P>
139
140<P>
141The functional interface of SoftFloat <NOBR>Release 3</NOBR> and later differs
142in many details from the releases that came before.
143For specifics of these differences, see <NOBR>section 9</NOBR> below,
144<I>Changes from SoftFloat <NOBR>Release 2</NOBR></I>.
145</P>
146
147
148<H2>2. Limitations</H2>
149
150<P>
151SoftFloat assumes the computer has an addressable byte size of 8 or
152<NOBR>16 bits</NOBR>.
153(Nearly all computers in use today have <NOBR>8-bit</NOBR> bytes.)
154</P>
155
156<P>
157SoftFloat is written in C and is designed to work with other C code.
158The C compiler used must conform at a minimum to the 1989 ANSI standard for the
159C language (same as the 1990 ISO standard) and must in addition support basic
160arithmetic on <NOBR>64-bit</NOBR> integers.
161Earlier releases of SoftFloat included implementations of <NOBR>32-bit</NOBR>
162single-precision and <NOBR>64-bit</NOBR> double-precision floating-point that
163did not require <NOBR>64-bit</NOBR> integers, but this option is not supported
164starting with <NOBR>Release 3</NOBR>.
165Since 1999, ISO standards for C have mandated compiler support for
166<NOBR>64-bit</NOBR> integers.
167A compiler conforming to the 1999 C Standard or later is recommended but not
168strictly required.
169</P>
170
171<P>
172Most operations not required by the original 1985 version of the IEEE
173Floating-Point Standard but added in the 2008 version are not yet supported in
174SoftFloat <NOBR>Release 3e</NOBR>.
175</P>
176
177
178<H2>3. Acknowledgments and License</H2>
179
180<P>
181The SoftFloat package was written by me, <NOBR>John R.</NOBR> Hauser.
182<NOBR>Release 3</NOBR> of SoftFloat was a completely new implementation
183supplanting earlier releases.
184The project to create <NOBR>Release 3</NOBR> (now <NOBR>through 3e</NOBR>) was
185done in the employ of the University of California, Berkeley, within the
186Department of Electrical Engineering and Computer Sciences, first for the
187Parallel Computing Laboratory (Par Lab) and then for the ASPIRE Lab.
188The work was officially overseen by Prof. Krste Asanovic, with funding provided
189by these sources:
190<BLOCKQUOTE>
191<TABLE>
192<COL>
193<COL WIDTH=10>
194<COL>
195<TR>
196<TD VALIGN=TOP><NOBR>Par Lab:</NOBR></TD>
197<TD></TD>
198<TD>
199Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery
200(Award #DIG07-10227), with additional support from Par Lab affiliates Nokia,
201NVIDIA, Oracle, and Samsung.
202</TD>
203</TR>
204<TR>
205<TD VALIGN=TOP><NOBR>ASPIRE Lab:</NOBR></TD>
206<TD></TD>
207<TD>
208DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from
209ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA,
210Oracle, and Samsung.
211</TD>
212</TR>
213</TABLE>
214</BLOCKQUOTE>
215</P>
216
217<P>
218The following applies to the whole of SoftFloat <NOBR>Release 3e</NOBR> as well
219as to each source file individually.
220</P>
221
222<P>
223Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the
224University of California.
225All rights reserved.
226</P>
227
228<P>
229Redistribution and use in source and binary forms, with or without
230modification, are permitted provided that the following conditions are met:
231<OL>
232
233<LI>
234<P>
235Redistributions of source code must retain the above copyright notice, this
236list of conditions, and the following disclaimer.
237</P>
238
239<LI>
240<P>
241Redistributions in binary form must reproduce the above copyright notice, this
242list of conditions, and the following disclaimer in the documentation and/or
243other materials provided with the distribution.
244</P>
245
246<LI>
247<P>
248Neither the name of the University nor the names of its contributors may be
249used to endorse or promote products derived from this software without specific
250prior written permission.
251</P>
252
253</OL>
254</P>
255
256<P>
257THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS &ldquo;AS IS&rdquo;,
258AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
259IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
260DISCLAIMED.
261IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
262INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
263BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
264DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
265LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
266OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
267ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
268</P>
269
270
271<H2>4. Types and Functions</H2>
272
273<P>
274The types and functions of SoftFloat are declared in header file
275<CODE>softfloat.h</CODE>.
276</P>
277
278<H3>4.1. Boolean and Integer Types</H3>
279
280<P>
281Header file <CODE>softfloat.h</CODE> depends on standard headers
282<CODE>&lt;stdbool.h&gt;</CODE> and <CODE>&lt;stdint.h&gt;</CODE> to define type
283<CODE>bool</CODE> and several integer types.
284These standard headers have been part of the ISO C Standard Library since 1999.
285With any recent compiler, they are likely to be supported, even if the compiler
286does not claim complete conformance to the latest ISO C Standard.
287For older or nonstandard compilers, a port of SoftFloat may have substitutes
288for these headers.
289Header <CODE>softfloat.h</CODE> depends only on the name <CODE>bool</CODE> from
290<CODE>&lt;stdbool.h&gt;</CODE> and on these type names from
291<CODE>&lt;stdint.h&gt;</CODE>:
292<BLOCKQUOTE>
293<PRE>
294uint16_t
295uint32_t
296uint64_t
297int32_t
298int64_t
299uint_fast8_t
300uint_fast32_t
301uint_fast64_t
302int_fast32_t
303int_fast64_t
304</PRE>
305</BLOCKQUOTE>
306</P>
307
308
309<H3>4.2. Floating-Point Types</H3>
310
311<P>
312The <CODE>softfloat.h</CODE> header defines five floating-point types:
313<BLOCKQUOTE>
314<TABLE CELLSPACING=0 CELLPADDING=0>
315<TR>
316<TD><CODE>float16_t</CODE></TD>
317<TD><NOBR>16-bit</NOBR> half-precision binary format</TD>
318</TR>
319<TR>
320<TD><CODE>float32_t</CODE></TD>
321<TD><NOBR>32-bit</NOBR> single-precision binary format</TD>
322</TR>
323<TR>
324<TD><CODE>float64_t</CODE></TD>
325<TD><NOBR>64-bit</NOBR> double-precision binary format</TD>
326</TR>
327<TR>
328<TD><CODE>extFloat80_t&nbsp;&nbsp;&nbsp;</CODE></TD>
329<TD><NOBR>80-bit</NOBR> double-extended-precision binary format (old Intel or
330Motorola format)</TD>
331</TR>
332<TR>
333<TD><CODE>float128_t</CODE></TD>
334<TD><NOBR>128-bit</NOBR> quadruple-precision binary format</TD>
335</TR>
336</TABLE>
337</BLOCKQUOTE>
338The non-extended types are each exactly the size specified:
339<NOBR>16 bits</NOBR> for <CODE>float16_t</CODE>, <NOBR>32 bits</NOBR> for
340<CODE>float32_t</CODE>, <NOBR>64 bits</NOBR> for <CODE>float64_t</CODE>, and
341<NOBR>128 bits</NOBR> for <CODE>float128_t</CODE>.
342Aside from these size requirements, the definitions of all these types may
343differ for different ports of SoftFloat to specific systems.
344A given port of SoftFloat may or may not define some of the floating-point
345types as aliases for the C standard types <CODE>float</CODE>,
346<CODE>double</CODE>, and <CODE>long</CODE> <CODE>double</CODE>.
347</P>
348
349<P>
350Header file <CODE>softfloat.h</CODE> also defines a structure,
351<CODE>struct</CODE> <CODE>extFloat80M</CODE>, for the representation of
352<NOBR>80-bit</NOBR> double-extended-precision floating-point values in memory.
353This structure is the same size as type <CODE>extFloat80_t</CODE> and contains
354at least these two fields (not necessarily in this order):
355<BLOCKQUOTE>
356<PRE>
357uint16_t signExp;
358uint64_t signif;
359</PRE>
360</BLOCKQUOTE>
361Field <CODE>signExp</CODE> contains the sign and exponent of the floating-point
362value, with the sign in the most significant bit (<NOBR>bit 15</NOBR>) and the
363encoded exponent in the other <NOBR>15 bits</NOBR>.
364Field <CODE>signif</CODE> is the complete <NOBR>64-bit</NOBR> significand of
365the floating-point value.
366(In the usual encoding for <NOBR>80-bit</NOBR> extended floating-point, the
367leading <NOBR>1 bit</NOBR> of normalized numbers is not implicit but is stored
368in the most significant bit of the significand.)
369</P>
370
371<H3>4.3. Supported Floating-Point Functions</H3>
372
373<P>
374SoftFloat implements these arithmetic operations for its floating-point types:
375<UL>
376<LI>
377conversions between any two floating-point formats;
378<LI>
379for each floating-point format, conversions to and from signed and unsigned
380<NOBR>32-bit</NOBR> and <NOBR>64-bit</NOBR> integers;
381<LI>
382for each format, the usual addition, subtraction, multiplication, division, and
383square root operations;
384<LI>
385for each format except <CODE>extFloat80_t</CODE>, the fused multiply-add
386operation defined by the IEEE Standard;
387<LI>
388for each format, the floating-point remainder operation defined by the IEEE
389Standard;
390<LI>
391for each format, a &ldquo;round to integer&rdquo; operation that rounds to the
392nearest integer value in the same format; and
393<LI>
394comparisons between two values in the same floating-point format.
395</UL>
396</P>
397
398<P>
399The following operations required by the 2008 IEEE Floating-Point Standard are
400not supported in SoftFloat <NOBR>Release 3e</NOBR>:
401<UL>
402<LI>
403<B>nextUp</B>, <B>nextDown</B>, <B>minNum</B>, <B>maxNum</B>, <B>minNumMag</B>,
404<B>maxNumMag</B>, <B>scaleB</B>, and <B>logB</B>;
405<LI>
406conversions between floating-point formats and decimal or hexadecimal character
407sequences;
408<LI>
409all &ldquo;quiet-computation&rdquo; operations (<B>copy</B>, <B>negate</B>,
410<B>abs</B>, and <B>copySign</B>, which all involve only simple copying and/or
411manipulation of the floating-point sign bit); and
412<LI>
413all &ldquo;non-computational&rdquo; operations other than <B>isSignaling</B>
414(which is supported).
415</UL>
416</P>
417
418<H3>4.4. Non-canonical Representations in <CODE>extFloat80_t</CODE></H3>
419
420<P>
421Because the <NOBR>80-bit</NOBR> double-extended-precision format,
422<CODE>extFloat80_t</CODE>, stores an explicit leading significand bit, many
423finite floating-point numbers are encodable in this type in multiple equivalent
424forms.
425Of these multiple encodings, there is always a unique one with the least
426encoded exponent value, and this encoding is considered the <I>canonical</I>
427representation of the floating-point number.
428Any other equivalent representations (having a higher encoded exponent value)
429are <I>non-canonical</I>.
430For a value in the subnormal range (including zero), the canonical
431representation always has an encoded exponent of zero and a leading significand
432bit <NOBR>of 0</NOBR>.
433For finite values outside the subnormal range, the canonical representation
434always has an encoded exponent that is nonzero and a leading significand bit
435<NOBR>of 1</NOBR>.
436</P>
437
438<P>
439For an infinity or NaN, the leading significand bit is similarly expected to
440<NOBR>be 1</NOBR>.
441An infinity or NaN with a leading significand bit <NOBR>of 0</NOBR> is again
442considered non-canonical.
443Hence, altogether, to be canonical, a value of type <CODE>extFloat80_t</CODE>
444must have a leading significand bit <NOBR>of 1</NOBR>, unless the value is
445subnormal or zero, in which case the leading significand bit and the encoded
446exponent must both be zero.
447</P>
448
449<P>
450SoftFloat&rsquo;s functions are not guaranteed to operate as expected when
451inputs of type <CODE>extFloat80_t</CODE> are non-canonical.
452Assuming all of a function&rsquo;s <CODE>extFloat80_t</CODE> inputs (if any)
453are canonical, function outputs of type <CODE>extFloat80_t</CODE> will always
454be canonical.
455</P>
456
457<H3>4.5. Conventions for Passing Arguments and Results</H3>
458
459<P>
460Values that are at most <NOBR>64 bits</NOBR> in size (i.e., not the
461<NOBR>80-bit</NOBR> or <NOBR>128-bit</NOBR> floating-point formats) are in all
462cases passed as function arguments by value.
463Likewise, when an output of a function is no more than <NOBR>64 bits</NOBR>, it
464is always returned directly as the function result.
465Thus, for example, the SoftFloat function for adding two <NOBR>64-bit</NOBR>
466floating-point values has this simple signature:
467<BLOCKQUOTE>
468<CODE>float64_t f64_add( float64_t, float64_t );</CODE>
469</BLOCKQUOTE>
470</P>
471
472<P>
473The story is more complex when function inputs and outputs are
474<NOBR>80-bit</NOBR> and <NOBR>128-bit</NOBR> floating-point.
475For these types, SoftFloat always provides a function that passes these larger
476values into or out of the function indirectly, via pointers.
477For example, for adding two <NOBR>128-bit</NOBR> floating-point values,
478SoftFloat supplies this function:
479<BLOCKQUOTE>
480<CODE>void f128M_add( const float128_t *, const float128_t *, float128_t * );</CODE>
481</BLOCKQUOTE>
482The first two arguments point to the values to be added, and the last argument
483points to the location where the sum will be stored.
484The <CODE>M</CODE> in the name <CODE>f128M_add</CODE> is mnemonic for the fact
485that the <NOBR>128-bit</NOBR> inputs and outputs are &ldquo;in memory&rdquo;,
486pointed to by pointer arguments.
487</P>
488
489<P>
490All ports of SoftFloat implement these <I>pass-by-pointer</I> functions for
491types <CODE>extFloat80_t</CODE> and <CODE>float128_t</CODE>.
492At the same time, SoftFloat ports may also implement alternate versions of
493these same functions that pass <CODE>extFloat80_t</CODE> and
494<CODE>float128_t</CODE> by value, like the smaller formats.
495Thus, besides the function with name <CODE>f128M_add</CODE> shown above, a
496SoftFloat port may also supply an equivalent function with this signature:
497<BLOCKQUOTE>
498<CODE>float128_t f128_add( float128_t, float128_t );</CODE>
499</BLOCKQUOTE>
500</P>
501
502<P>
503As a general rule, on computers where the machine word size is
504<NOBR>32 bits</NOBR> or smaller, only the pass-by-pointer versions of functions
505(e.g., <CODE>f128M_add</CODE>) are provided for types <CODE>extFloat80_t</CODE>
506and <CODE>float128_t</CODE>, because passing such large types directly can have
507significant extra cost.
508On computers where the word size is <NOBR>64 bits</NOBR> or larger, both
509function versions (<CODE>f128M_add</CODE> and <CODE>f128_add</CODE>) are
510provided, because the cost of passing by value is then more reasonable.
511Applications that must be portable accross both classes of computers must use
512the pointer-based functions, as these are always implemented.
513However, if it is known that SoftFloat includes the by-value functions for all
514platforms of interest, programmers can use whichever version they prefer.
515</P>
516
517
518<H2>5. Reserved Names</H2>
519
520<P>
521In addition to the variables and functions documented here, SoftFloat defines
522some symbol names for its own private use.
523These private names always begin with the prefix
524&lsquo;<CODE>softfloat_</CODE>&rsquo;.
525When a program includes header <CODE>softfloat.h</CODE> or links with the
526SoftFloat library, all names with prefix &lsquo;<CODE>softfloat_</CODE>&rsquo;
527are reserved for possible use by SoftFloat.
528Applications that use SoftFloat should not define their own names with this
529prefix, and should reference only such names as are documented.
530</P>
531
532
533<H2>6. Mode Variables</H2>
534
535<P>
536The following global variables control rounding mode, underflow detection, and
537the <NOBR>80-bit</NOBR> extended format&rsquo;s rounding precision:
538<BLOCKQUOTE>
539<CODE>softfloat_roundingMode</CODE><BR>
540<CODE>softfloat_detectTininess</CODE><BR>
541<CODE>extF80_roundingPrecision</CODE>
542</BLOCKQUOTE>
543These mode variables are covered in the next several subsections.
544For some SoftFloat ports, these variables may be <I>per-thread</I> (declared
545<CODE>thread_local</CODE>), meaning that different execution threads have their
546own separate copies of the variables.
547</P>
548
549<H3>6.1. Rounding Mode</H3>
550
551<P>
552All five rounding modes defined by the 2008 IEEE Floating-Point Standard are
553implemented for all operations that require rounding.
554Some ports of SoftFloat may also implement the <I>round-to-odd</I> mode.
555</P>
556
557<P>
558The rounding mode is selected by the global variable
559<BLOCKQUOTE>
560<CODE>uint_fast8_t softfloat_roundingMode;</CODE>
561</BLOCKQUOTE>
562This variable may be set to one of the values
563<BLOCKQUOTE>
564<TABLE CELLSPACING=0 CELLPADDING=0>
565<TR>
566<TD><CODE>softfloat_round_near_even</CODE></TD>
567<TD>round to nearest, with ties to even</TD>
568</TR>
569<TR>
570<TD><CODE>softfloat_round_near_maxMag&nbsp;&nbsp;</CODE></TD>
571<TD>round to nearest, with ties to maximum magnitude (away from zero)</TD>
572</TR>
573<TR>
574<TD><CODE>softfloat_round_minMag</CODE></TD>
575<TD>round to minimum magnitude (toward zero)</TD>
576</TR>
577<TR>
578<TD><CODE>softfloat_round_min</CODE></TD>
579<TD>round to minimum (down)</TD>
580</TR>
581<TR>
582<TD><CODE>softfloat_round_max</CODE></TD>
583<TD>round to maximum (up)</TD>
584</TR>
585<TR>
586<TD><CODE>softfloat_round_odd</CODE></TD>
587<TD>round to odd (jamming), if supported by the SoftFloat port</TD>
588</TR>
589</TABLE>
590</BLOCKQUOTE>
591Variable <CODE>softfloat_roundingMode</CODE> is initialized to
592<CODE>softfloat_round_near_even</CODE>.
593</P>
594
595<P>
596When <CODE>softfloat_round_odd</CODE> is the rounding mode for a function that
597rounds to an integer value (either conversion to an integer format or a
598&lsquo;<CODE>roundToInt</CODE>&rsquo; function), if the input is not already an
599integer, the rounded result is the closest <EM>odd</EM> integer.
600For other operations, this rounding mode acts as though the floating-point
601result is first rounded to minimum magnitude, the same as
602<CODE>softfloat_round_minMag</CODE>, and then, if the result is inexact, the
603least-significant bit of the result is set <NOBR>to 1</NOBR>.
604Rounding to odd is also known as <EM>jamming</EM>.
605</P>
606
607<H3>6.2. Underflow Detection</H3>
608
609<P>
610In the terminology of the IEEE Standard, SoftFloat can detect tininess for
611underflow either before or after rounding.
612The choice is made by the global variable
613<BLOCKQUOTE>
614<CODE>uint_fast8_t softfloat_detectTininess;</CODE>
615</BLOCKQUOTE>
616which can be set to either
617<BLOCKQUOTE>
618<CODE>softfloat_tininess_beforeRounding</CODE><BR>
619<CODE>softfloat_tininess_afterRounding</CODE>
620</BLOCKQUOTE>
621Detecting tininess after rounding is usually better because it results in fewer
622spurious underflow signals.
623The other option is provided for compatibility with some systems.
624Like most systems (and as required by the newer 2008 IEEE Standard), SoftFloat
625always detects loss of accuracy for underflow as an inexact result.
626</P>
627
628<H3>6.3. Rounding Precision for the <NOBR>80-Bit</NOBR> Extended Format</H3>
629
630<P>
631For <CODE>extFloat80_t</CODE> only, the rounding precision of the basic
632arithmetic operations is controlled by the global variable
633<BLOCKQUOTE>
634<CODE>uint_fast8_t extF80_roundingPrecision;</CODE>
635</BLOCKQUOTE>
636The operations affected are:
637<BLOCKQUOTE>
638<CODE>extF80_add</CODE><BR>
639<CODE>extF80_sub</CODE><BR>
640<CODE>extF80_mul</CODE><BR>
641<CODE>extF80_div</CODE><BR>
642<CODE>extF80_sqrt</CODE>
643</BLOCKQUOTE>
644When <CODE>extF80_roundingPrecision</CODE> is set to its default value of 80,
645these operations are rounded to the full precision of the <NOBR>80-bit</NOBR>
646double-extended-precision format, like occurs for other formats.
647Setting <CODE>extF80_roundingPrecision</CODE> to 32 or to 64 causes the
648operations listed to be rounded to <NOBR>32-bit</NOBR> precision (equivalent to
649<CODE>float32_t</CODE>) or to <NOBR>64-bit</NOBR> precision (equivalent to
650<CODE>float64_t</CODE>), respectively.
651When rounding to reduced precision, additional bits in the result significand
652beyond the rounding point are set to zero.
653The consequences of setting <CODE>extF80_roundingPrecision</CODE> to a value
654other than 32, 64, or 80 is not specified.
655Operations other than the ones listed above are not affected by
656<CODE>extF80_roundingPrecision</CODE>.
657</P>
658
659
660<H2>7. Exceptions and Exception Flags</H2>
661
662<P>
663All five exception flags required by the IEEE Floating-Point Standard are
664implemented.
665Each flag is stored as a separate bit in the global variable
666<BLOCKQUOTE>
667<CODE>uint_fast8_t softfloat_exceptionFlags;</CODE>
668</BLOCKQUOTE>
669The positions of the exception flag bits within this variable are determined by
670the bit masks
671<BLOCKQUOTE>
672<CODE>softfloat_flag_inexact</CODE><BR>
673<CODE>softfloat_flag_underflow</CODE><BR>
674<CODE>softfloat_flag_overflow</CODE><BR>
675<CODE>softfloat_flag_infinite</CODE><BR>
676<CODE>softfloat_flag_invalid</CODE>
677</BLOCKQUOTE>
678Variable <CODE>softfloat_exceptionFlags</CODE> is initialized to all zeros,
679meaning no exceptions.
680</P>
681
682<P>
683For some SoftFloat ports, <CODE>softfloat_exceptionFlags</CODE> may be
684<I>per-thread</I> (declared <CODE>thread_local</CODE>), meaning that different
685execution threads have their own separate instances of it.
686</P>
687
688<P>
689An individual exception flag can be cleared with the statement
690<BLOCKQUOTE>
691<CODE>softfloat_exceptionFlags &= ~softfloat_flag_&lt;<I>exception</I>&gt;;</CODE>
692</BLOCKQUOTE>
693where <CODE>&lt;<I>exception</I>&gt;</CODE> is the appropriate name.
694To raise a floating-point exception, function <CODE>softfloat_raiseFlags</CODE>
695should normally be used.
696</P>
697
698<P>
699When SoftFloat detects an exception other than <I>inexact</I>, it calls
700<CODE>softfloat_raiseFlags</CODE>.
701The default version of this function simply raises the corresponding exception
702flags.
703Particular ports of SoftFloat may support alternate behavior, such as exception
704traps, by modifying the default <CODE>softfloat_raiseFlags</CODE>.
705A program may also supply its own <CODE>softfloat_raiseFlags</CODE> function to
706override the one from the SoftFloat library.
707</P>
708
709<P>
710Because inexact results occur frequently under most circumstances (and thus are
711hardly exceptional), SoftFloat does not ordinarily call
712<CODE>softfloat_raiseFlags</CODE> for <I>inexact</I> exceptions.
713It does always raise the <I>inexact</I> exception flag as required.
714</P>
715
716
717<H2>8. Function Details</H2>
718
719<P>
720In this section, <CODE>&lt;<I>float</I>&gt;</CODE> appears in function names as
721a substitute for one of these abbreviations:
722<BLOCKQUOTE>
723<TABLE CELLSPACING=0 CELLPADDING=0>
724<TR>
725<TD><CODE>f16</CODE></TD>
726<TD>indicates <CODE>float16_t</CODE>, passed by value</TD>
727</TR>
728<TR>
729<TD><CODE>f32</CODE></TD>
730<TD>indicates <CODE>float32_t</CODE>, passed by value</TD>
731</TR>
732<TR>
733<TD><CODE>f64</CODE></TD>
734<TD>indicates <CODE>float64_t</CODE>, passed by value</TD>
735</TR>
736<TR>
737<TD><CODE>extF80M&nbsp;&nbsp;&nbsp;</CODE></TD>
738<TD>indicates <CODE>extFloat80_t</CODE>, passed indirectly via pointers</TD>
739</TR>
740<TR>
741<TD><CODE>extF80</CODE></TD>
742<TD>indicates <CODE>extFloat80_t</CODE>, passed by value</TD>
743</TR>
744<TR>
745<TD><CODE>f128M</CODE></TD>
746<TD>indicates <CODE>float128_t</CODE>, passed indirectly via pointers</TD>
747</TR>
748<TR>
749<TD><CODE>f128</CODE></TD>
750<TD>indicates <CODE>float128_t</CODE>, passed by value</TD>
751</TR>
752</TABLE>
753</BLOCKQUOTE>
754The circumstances under which values of floating-point types
755<CODE>extFloat80_t</CODE> and <CODE>float128_t</CODE> may be passed either by
756value or indirectly via pointers was discussed earlier in
757<NOBR>section 4.5</NOBR>, <I>Conventions for Passing Arguments and Results</I>.
758</P>
759
760<H3>8.1. Conversions from Integer to Floating-Point</H3>
761
762<P>
763All conversions from a <NOBR>32-bit</NOBR> or <NOBR>64-bit</NOBR> integer,
764signed or unsigned, to a floating-point format are supported.
765Functions performing these conversions have these names:
766<BLOCKQUOTE>
767<CODE>ui32_to_&lt;<I>float</I>&gt;</CODE><BR>
768<CODE>ui64_to_&lt;<I>float</I>&gt;</CODE><BR>
769<CODE>i32_to_&lt;<I>float</I>&gt;</CODE><BR>
770<CODE>i64_to_&lt;<I>float</I>&gt;</CODE>
771</BLOCKQUOTE>
772Conversions from <NOBR>32-bit</NOBR> integers to <NOBR>64-bit</NOBR>
773double-precision and larger formats are always exact, and likewise conversions
774from <NOBR>64-bit</NOBR> integers to <NOBR>80-bit</NOBR>
775double-extended-precision and <NOBR>128-bit</NOBR> quadruple-precision are also
776always exact.
777</P>
778
779<P>
780Each conversion function takes one input of the appropriate type and generates
781one output.
782The following illustrates the signatures of these functions in cases when the
783floating-point result is passed either by value or via pointers:
784<BLOCKQUOTE>
785<PRE>
786float64_t i32_to_f64( int32_t <I>a</I> );
787</PRE>
788<PRE>
789void i32_to_f128M( int32_t <I>a</I>, float128_t *<I>destPtr</I> );
790</PRE>
791</BLOCKQUOTE>
792</P>
793
794<H3>8.2. Conversions from Floating-Point to Integer</H3>
795
796<P>
797Conversions from a floating-point format to a <NOBR>32-bit</NOBR> or
798<NOBR>64-bit</NOBR> integer, signed or unsigned, are supported with these
799functions:
800<BLOCKQUOTE>
801<CODE>&lt;<I>float</I>&gt;_to_ui32</CODE><BR>
802<CODE>&lt;<I>float</I>&gt;_to_ui64</CODE><BR>
803<CODE>&lt;<I>float</I>&gt;_to_i32</CODE><BR>
804<CODE>&lt;<I>float</I>&gt;_to_i64</CODE>
805</BLOCKQUOTE>
806The functions have signatures as follows, depending on whether the
807floating-point input is passed by value or via pointers:
808<BLOCKQUOTE>
809<PRE>
810int_fast32_t f64_to_i32( float64_t <I>a</I>, uint_fast8_t <I>roundingMode</I>, bool <I>exact</I> );
811</PRE>
812<PRE>
813int_fast32_t
814 f128M_to_i32( const float128_t *<I>aPtr</I>, uint_fast8_t <I>roundingMode</I>, bool <I>exact</I> );
815</PRE>
816</BLOCKQUOTE>
817</P>
818
819<P>
820The <CODE><I>roundingMode</I></CODE> argument specifies the rounding mode for
821the conversion.
822The variable that usually indicates rounding mode,
823<CODE>softfloat_roundingMode</CODE>, is ignored.
824Argument <CODE><I>exact</I></CODE> determines whether the <I>inexact</I>
825exception flag is raised if the conversion is not exact.
826If <CODE><I>exact</I></CODE> is <CODE>true</CODE>, the <I>inexact</I> flag may
827be raised;
828otherwise, it will not be, even if the conversion is inexact.
829</P>
830
831<P>
832A conversion from floating-point to integer format raises the <I>invalid</I>
833exception if the source value cannot be rounded to a representable integer of
834the desired size (32 or 64 bits).
835In such circumstances, the integer result returned is determined by the
836particular port of SoftFloat, although typically this value will be either the
837maximum or minimum value of the integer format.
838The functions that convert to integer types never raise the floating-point
839<I>overflow</I> exception.
840</P>
841
842<P>
843Because languages such <NOBR>as C</NOBR> require that conversions to integers
844be rounded toward zero, the following functions are provided for improved speed
845and convenience:
846<BLOCKQUOTE>
847<CODE>&lt;<I>float</I>&gt;_to_ui32_r_minMag</CODE><BR>
848<CODE>&lt;<I>float</I>&gt;_to_ui64_r_minMag</CODE><BR>
849<CODE>&lt;<I>float</I>&gt;_to_i32_r_minMag</CODE><BR>
850<CODE>&lt;<I>float</I>&gt;_to_i64_r_minMag</CODE>
851</BLOCKQUOTE>
852These functions round only toward zero (to minimum magnitude).
853The signatures for these functions are the same as above without the redundant
854<CODE><I>roundingMode</I></CODE> argument:
855<BLOCKQUOTE>
856<PRE>
857int_fast32_t f64_to_i32_r_minMag( float64_t <I>a</I>, bool <I>exact</I> );
858</PRE>
859<PRE>
860int_fast32_t f128M_to_i32_r_minMag( const float128_t *<I>aPtr</I>, bool <I>exact</I> );
861</PRE>
862</BLOCKQUOTE>
863</P>
864
865<H3>8.3. Conversions Among Floating-Point Types</H3>
866
867<P>
868Conversions between floating-point formats are done by functions with these
869names:
870<BLOCKQUOTE>
871<CODE>&lt;<I>float</I>&gt;_to_&lt;<I>float</I>&gt;</CODE>
872</BLOCKQUOTE>
873All combinations of source and result type are supported where the source and
874result are different formats.
875There are four different styles of signature for these functions, depending on
876whether the input and the output floating-point values are passed by value or
877via pointers:
878<BLOCKQUOTE>
879<PRE>
880float32_t f64_to_f32( float64_t <I>a</I> );
881</PRE>
882<PRE>
883float32_t f128M_to_f32( const float128_t *<I>aPtr</I> );
884</PRE>
885<PRE>
886void f32_to_f128M( float32_t <I>a</I>, float128_t *<I>destPtr</I> );
887</PRE>
888<PRE>
889void extF80M_to_f128M( const extFloat80_t *<I>aPtr</I>, float128_t *<I>destPtr</I> );
890</PRE>
891</BLOCKQUOTE>
892</P>
893
894<P>
895Conversions from a smaller to a larger floating-point format are always exact
896and so require no rounding.
897</P>
898
899<H3>8.4. Basic Arithmetic Functions</H3>
900
901<P>
902The following basic arithmetic functions are provided:
903<BLOCKQUOTE>
904<CODE>&lt;<I>float</I>&gt;_add</CODE><BR>
905<CODE>&lt;<I>float</I>&gt;_sub</CODE><BR>
906<CODE>&lt;<I>float</I>&gt;_mul</CODE><BR>
907<CODE>&lt;<I>float</I>&gt;_div</CODE><BR>
908<CODE>&lt;<I>float</I>&gt;_sqrt</CODE>
909</BLOCKQUOTE>
910Each floating-point operation takes two operands, except for <CODE>sqrt</CODE>
911(square root) which takes only one.
912The operands and result are all of the same floating-point format.
913Signatures for these functions take the following forms:
914<BLOCKQUOTE>
915<PRE>
916float64_t f64_add( float64_t <I>a</I>, float64_t <I>b</I> );
917</PRE>
918<PRE>
919void
920 f128M_add(
921 const float128_t *<I>aPtr</I>, const float128_t *<I>bPtr</I>, float128_t *<I>destPtr</I> );
922</PRE>
923<PRE>
924float64_t f64_sqrt( float64_t <I>a</I> );
925</PRE>
926<PRE>
927void f128M_sqrt( const float128_t *<I>aPtr</I>, float128_t *<I>destPtr</I> );
928</PRE>
929</BLOCKQUOTE>
930When floating-point values are passed indirectly through pointers, arguments
931<CODE><I>aPtr</I></CODE> and <CODE><I>bPtr</I></CODE> point to the input
932operands, and the last argument, <CODE><I>destPtr</I></CODE>, points to the
933location where the result is stored.
934</P>
935
936<P>
937Rounding of the <NOBR>80-bit</NOBR> double-extended-precision
938(<CODE>extFloat80_t</CODE>) functions is affected by variable
939<CODE>extF80_roundingPrecision</CODE>, as explained earlier in
940<NOBR>section 6.3</NOBR>,
941<I>Rounding Precision for the <NOBR>80-Bit</NOBR> Extended Format</I>.
942</P>
943
944<H3>8.5. Fused Multiply-Add Functions</H3>
945
946<P>
947The 2008 version of the IEEE Floating-Point Standard defines a <I>fused
948multiply-add</I> operation that does a combined multiplication and addition
949with only a single rounding.
950SoftFloat implements fused multiply-add with functions
951<BLOCKQUOTE>
952<CODE>&lt;<I>float</I>&gt;_mulAdd</CODE>
953</BLOCKQUOTE>
954Unlike other operations, fused multiple-add is not supported for the
955<NOBR>80-bit</NOBR> double-extended-precision format,
956<CODE>extFloat80_t</CODE>.
957</P>
958
959<P>
960Depending on whether floating-point values are passed by value or via pointers,
961the fused multiply-add functions have signatures of these forms:
962<BLOCKQUOTE>
963<PRE>
964float64_t f64_mulAdd( float64_t <I>a</I>, float64_t <I>b</I>, float64_t <I>c</I> );
965</PRE>
966<PRE>
967void
968 f128M_mulAdd(
969 const float128_t *<I>aPtr</I>,
970 const float128_t *<I>bPtr</I>,
971 const float128_t *<I>cPtr</I>,
972 float128_t *<I>destPtr</I>
973 );
974</PRE>
975</BLOCKQUOTE>
976The functions compute
977<NOBR>(<CODE><I>a</I></CODE> &times; <CODE><I>b</I></CODE>)
978 + <CODE><I>c</I></CODE></NOBR>
979with a single rounding.
980When floating-point values are passed indirectly through pointers, arguments
981<CODE><I>aPtr</I></CODE>, <CODE><I>bPtr</I></CODE>, and
982<CODE><I>cPtr</I></CODE> point to operands <CODE><I>a</I></CODE>,
983<CODE><I>b</I></CODE>, and <CODE><I>c</I></CODE> respectively, and
984<CODE><I>destPtr</I></CODE> points to the location where the result is stored.
985</P>
986
987<P>
988If one of the multiplication operands <CODE><I>a</I></CODE> and
989<CODE><I>b</I></CODE> is infinite and the other is zero, these functions raise
990the invalid exception even if operand <CODE><I>c</I></CODE> is a quiet NaN.
991</P>
992
993<H3>8.6. Remainder Functions</H3>
994
995<P>
996For each format, SoftFloat implements the remainder operation defined by the
997IEEE Floating-Point Standard.
998The remainder functions have names
999<BLOCKQUOTE>
1000<CODE>&lt;<I>float</I>&gt;_rem</CODE>
1001</BLOCKQUOTE>
1002Each remainder operation takes two floating-point operands of the same format
1003and returns a result in the same format.
1004Depending on whether floating-point values are passed by value or via pointers,
1005the remainder functions have signatures of these forms:
1006<BLOCKQUOTE>
1007<PRE>
1008float64_t f64_rem( float64_t <I>a</I>, float64_t <I>b</I> );
1009</PRE>
1010<PRE>
1011void
1012 f128M_rem(
1013 const float128_t *<I>aPtr</I>, const float128_t *<I>bPtr</I>, float128_t *<I>destPtr</I> );
1014</PRE>
1015</BLOCKQUOTE>
1016When floating-point values are passed indirectly through pointers, arguments
1017<CODE><I>aPtr</I></CODE> and <CODE><I>bPtr</I></CODE> point to operands
1018<CODE><I>a</I></CODE> and <CODE><I>b</I></CODE> respectively, and
1019<CODE><I>destPtr</I></CODE> points to the location where the result is stored.
1020</P>
1021
1022<P>
1023The IEEE Standard remainder operation computes the value
1024<NOBR><CODE><I>a</I></CODE>
1025 &minus; <I>n</I> &times; <CODE><I>b</I></CODE></NOBR>,
1026where <I>n</I> is the integer closest to
1027<NOBR><CODE><I>a</I></CODE> &divide; <CODE><I>b</I></CODE></NOBR>.
1028If <NOBR><CODE><I>a</I></CODE> &divide; <CODE><I>b</I></CODE></NOBR> is exactly
1029halfway between two integers, <I>n</I> is the <EM>even</EM> integer closest to
1030<NOBR><CODE><I>a</I></CODE> &divide; <CODE><I>b</I></CODE></NOBR>.
1031The IEEE Standard&rsquo;s remainder operation is always exact and so requires
1032no rounding.
1033</P>
1034
1035<P>
1036Depending on the relative magnitudes of the operands, the remainder
1037functions can take considerably longer to execute than the other SoftFloat
1038functions.
1039This is an inherent characteristic of the remainder operation itself and is not
1040a flaw in the SoftFloat implementation.
1041</P>
1042
1043<H3>8.7. Round-to-Integer Functions</H3>
1044
1045<P>
1046For each format, SoftFloat implements the round-to-integer operation specified
1047by the IEEE Floating-Point Standard.
1048These functions are named
1049<BLOCKQUOTE>
1050<CODE>&lt;<I>float</I>&gt;_roundToInt</CODE>
1051</BLOCKQUOTE>
1052Each round-to-integer operation takes a single floating-point operand.
1053This operand is rounded to an integer according to a specified rounding mode,
1054and the resulting integer value is returned in the same floating-point format.
1055(Note that the result is not an integer type.)
1056</P>
1057
1058<P>
1059The signatures of the round-to-integer functions are similar to those for
1060conversions to an integer type:
1061<BLOCKQUOTE>
1062<PRE>
1063float64_t f64_roundToInt( float64_t <I>a</I>, uint_fast8_t <I>roundingMode</I>, bool <I>exact</I> );
1064</PRE>
1065<PRE>
1066void
1067 f128M_roundToInt(
1068 const float128_t *<I>aPtr</I>,
1069 uint_fast8_t <I>roundingMode</I>,
1070 bool <I>exact</I>,
1071 float128_t *<I>destPtr</I>
1072 );
1073</PRE>
1074</BLOCKQUOTE>
1075When floating-point values are passed indirectly through pointers,
1076<CODE><I>aPtr</I></CODE> points to the input operand and
1077<CODE><I>destPtr</I></CODE> points to the location where the result is stored.
1078</P>
1079
1080<P>
1081The <CODE><I>roundingMode</I></CODE> argument specifies the rounding mode to
1082apply.
1083The variable that usually indicates rounding mode,
1084<CODE>softfloat_roundingMode</CODE>, is ignored.
1085Argument <CODE><I>exact</I></CODE> determines whether the <I>inexact</I>
1086exception flag is raised if the conversion is not exact.
1087If <CODE><I>exact</I></CODE> is <CODE>true</CODE>, the <I>inexact</I> flag may
1088be raised;
1089otherwise, it will not be, even if the conversion is inexact.
1090</P>
1091
1092<H3>8.8. Comparison Functions</H3>
1093
1094<P>
1095For each format, the following floating-point comparison functions are
1096provided:
1097<BLOCKQUOTE>
1098<CODE>&lt;<I>float</I>&gt;_eq</CODE><BR>
1099<CODE>&lt;<I>float</I>&gt;_le</CODE><BR>
1100<CODE>&lt;<I>float</I>&gt;_lt</CODE>
1101</BLOCKQUOTE>
1102Each comparison takes two operands of the same type and returns a Boolean.
1103The abbreviation <CODE>eq</CODE> stands for &ldquo;equal&rdquo; (=);
1104<CODE>le</CODE> stands for &ldquo;less than or equal&rdquo; (&le;);
1105and <CODE>lt</CODE> stands for &ldquo;less than&rdquo; (&lt;).
1106Depending on whether the floating-point operands are passed by value or via
1107pointers, the comparison functions have signatures of these forms:
1108<BLOCKQUOTE>
1109<PRE>
1110bool f64_eq( float64_t <I>a</I>, float64_t <I>b</I> );
1111</PRE>
1112<PRE>
1113bool f128M_eq( const float128_t *<I>aPtr</I>, const float128_t *<I>bPtr</I> );
1114</PRE>
1115</BLOCKQUOTE>
1116</P>
1117
1118<P>
1119The usual greater-than (&gt;), greater-than-or-equal (&ge;), and not-equal
1120(&ne;) comparisons are easily obtained from the functions provided.
1121The not-equal function is just the logical complement of the equal function.
1122The greater-than-or-equal function is identical to the less-than-or-equal
1123function with the arguments in reverse order, and likewise the greater-than
1124function is identical to the less-than function with the arguments reversed.
1125</P>
1126
1127<P>
1128The IEEE Floating-Point Standard specifies that the less-than-or-equal and
1129less-than comparisons by default raise the <I>invalid</I> exception if either
1130operand is any kind of NaN.
1131Equality comparisons, on the other hand, are defined by default to raise the
1132<I>invalid</I> exception only for signaling NaNs, not quiet NaNs.
1133For completeness, SoftFloat provides these complementary functions:
1134<BLOCKQUOTE>
1135<CODE>&lt;<I>float</I>&gt;_eq_signaling</CODE><BR>
1136<CODE>&lt;<I>float</I>&gt;_le_quiet</CODE><BR>
1137<CODE>&lt;<I>float</I>&gt;_lt_quiet</CODE>
1138</BLOCKQUOTE>
1139The <CODE>signaling</CODE> equality comparisons are identical to the default
1140equality comparisons except that the <I>invalid</I> exception is raised for any
1141NaN input, not just for signaling NaNs.
1142Similarly, the <CODE>quiet</CODE> comparison functions are identical to their
1143default counterparts except that the <I>invalid</I> exception is not raised for
1144quiet NaNs.
1145</P>
1146
1147<H3>8.9. Signaling NaN Test Functions</H3>
1148
1149<P>
1150Functions for testing whether a floating-point value is a signaling NaN are
1151provided with these names:
1152<BLOCKQUOTE>
1153<CODE>&lt;<I>float</I>&gt;_isSignalingNaN</CODE>
1154</BLOCKQUOTE>
1155The functions take one floating-point operand and return a Boolean indicating
1156whether the operand is a signaling NaN.
1157Accordingly, the functions have the forms
1158<BLOCKQUOTE>
1159<PRE>
1160bool f64_isSignalingNaN( float64_t <I>a</I> );
1161</PRE>
1162<PRE>
1163bool f128M_isSignalingNaN( const float128_t *<I>aPtr</I> );
1164</PRE>
1165</BLOCKQUOTE>
1166</P>
1167
1168<H3>8.10. Raise-Exception Function</H3>
1169
1170<P>
1171SoftFloat provides a single function for raising floating-point exceptions:
1172<BLOCKQUOTE>
1173<PRE>
1174void softfloat_raiseFlags( uint_fast8_t <I>exceptions</I> );
1175</PRE>
1176</BLOCKQUOTE>
1177The <CODE><I>exceptions</I></CODE> argument is a mask indicating the set of
1178exceptions to raise.
1179(See earlier section 7, <I>Exceptions and Exception Flags</I>.)
1180In addition to setting the specified exception flags in variable
1181<CODE>softfloat_exceptionFlags</CODE>, the <CODE>softfloat_raiseFlags</CODE>
1182function may cause a trap or abort appropriate for the current system.
1183</P>
1184
1185
1186<H2>9. Changes from SoftFloat <NOBR>Release 2</NOBR></H2>
1187
1188<P>
1189Apart from a change in the legal use license, <NOBR>Release 3</NOBR> of
1190SoftFloat introduced numerous technical differences compared to earlier
1191releases.
1192</P>
1193
1194<H3>9.1. Name Changes</H3>
1195
1196<P>
1197The most obvious and pervasive difference compared to <NOBR>Release 2</NOBR>
1198is that the names of most functions and variables have changed, even when the
1199behavior has not.
1200First, the floating-point types, the mode variables, the exception flags
1201variable, the function to raise exceptions, and various associated constants
1202have been renamed as follows:
1203<BLOCKQUOTE>
1204<TABLE>
1205<TR>
1206<TD>old name, Release 2:</TD>
1207<TD>new name, Release 3:</TD>
1208</TR>
1209<TR>
1210<TD><CODE>float32</CODE></TD>
1211<TD><CODE>float32_t</CODE></TD>
1212</TR>
1213<TR>
1214<TD><CODE>float64</CODE></TD>
1215<TD><CODE>float64_t</CODE></TD>
1216</TR>
1217<TR>
1218<TD><CODE>floatx80</CODE></TD>
1219<TD><CODE>extFloat80_t</CODE></TD>
1220</TR>
1221<TR>
1222<TD><CODE>float128</CODE></TD>
1223<TD><CODE>float128_t</CODE></TD>
1224</TR>
1225<TR>
1226<TD><CODE>float_rounding_mode</CODE></TD>
1227<TD><CODE>softfloat_roundingMode</CODE></TD>
1228</TR>
1229<TR>
1230<TD><CODE>float_round_nearest_even</CODE></TD>
1231<TD><CODE>softfloat_round_near_even</CODE></TD>
1232</TR>
1233<TR>
1234<TD><CODE>float_round_to_zero</CODE></TD>
1235<TD><CODE>softfloat_round_minMag</CODE></TD>
1236</TR>
1237<TR>
1238<TD><CODE>float_round_down</CODE></TD>
1239<TD><CODE>softfloat_round_min</CODE></TD>
1240</TR>
1241<TR>
1242<TD><CODE>float_round_up</CODE></TD>
1243<TD><CODE>softfloat_round_max</CODE></TD>
1244</TR>
1245<TR>
1246<TD><CODE>float_detect_tininess</CODE></TD>
1247<TD><CODE>softfloat_detectTininess</CODE></TD>
1248</TR>
1249<TR>
1250<TD><CODE>float_tininess_before_rounding&nbsp;&nbsp;&nbsp;&nbsp;</CODE></TD>
1251<TD><CODE>softfloat_tininess_beforeRounding</CODE></TD>
1252</TR>
1253<TR>
1254<TD><CODE>float_tininess_after_rounding</CODE></TD>
1255<TD><CODE>softfloat_tininess_afterRounding</CODE></TD>
1256</TR>
1257<TR>
1258<TD><CODE>floatx80_rounding_precision</CODE></TD>
1259<TD><CODE>extF80_roundingPrecision</CODE></TD>
1260</TR>
1261<TR>
1262<TD><CODE>float_exception_flags</CODE></TD>
1263<TD><CODE>softfloat_exceptionFlags</CODE></TD>
1264</TR>
1265<TR>
1266<TD><CODE>float_flag_inexact</CODE></TD>
1267<TD><CODE>softfloat_flag_inexact</CODE></TD>
1268</TR>
1269<TR>
1270<TD><CODE>float_flag_underflow</CODE></TD>
1271<TD><CODE>softfloat_flag_underflow</CODE></TD>
1272</TR>
1273<TR>
1274<TD><CODE>float_flag_overflow</CODE></TD>
1275<TD><CODE>softfloat_flag_overflow</CODE></TD>
1276</TR>
1277<TR>
1278<TD><CODE>float_flag_divbyzero</CODE></TD>
1279<TD><CODE>softfloat_flag_infinite</CODE></TD>
1280</TR>
1281<TR>
1282<TD><CODE>float_flag_invalid</CODE></TD>
1283<TD><CODE>softfloat_flag_invalid</CODE></TD>
1284</TR>
1285<TR>
1286<TD><CODE>float_raise</CODE></TD>
1287<TD><CODE>softfloat_raiseFlags</CODE></TD>
1288</TR>
1289</TABLE>
1290</BLOCKQUOTE>
1291</P>
1292
1293<P>
1294Furthermore, <NOBR>Release 3</NOBR> adopted the following new abbreviations for
1295function names:
1296<BLOCKQUOTE>
1297<TABLE>
1298<TR>
1299<TD>used in names in Release 2:<CODE>&nbsp;&nbsp;&nbsp;&nbsp;</CODE></TD>
1300<TD>used in names in Release 3:</TD>
1301</TR>
1302<TR> <TD><CODE>int32</CODE></TD> <TD><CODE>i32</CODE></TD> </TR>
1303<TR> <TD><CODE>int64</CODE></TD> <TD><CODE>i64</CODE></TD> </TR>
1304<TR> <TD><CODE>float32</CODE></TD> <TD><CODE>f32</CODE></TD> </TR>
1305<TR> <TD><CODE>float64</CODE></TD> <TD><CODE>f64</CODE></TD> </TR>
1306<TR> <TD><CODE>floatx80</CODE></TD> <TD><CODE>extF80</CODE></TD> </TR>
1307<TR> <TD><CODE>float128</CODE></TD> <TD><CODE>f128</CODE></TD> </TR>
1308</TABLE>
1309</BLOCKQUOTE>
1310Thus, for example, the function to add two <NOBR>32-bit</NOBR> floating-point
1311numbers, previously called <CODE>float32_add</CODE> in <NOBR>Release 2</NOBR>,
1312is now <CODE>f32_add</CODE>.
1313Lastly, there have been a few other changes to function names:
1314<BLOCKQUOTE>
1315<TABLE>
1316<TR>
1317<TD>used in names in Release 2:<CODE>&nbsp;&nbsp;&nbsp;</CODE></TD>
1318<TD>used in names in Release 3:<CODE>&nbsp;&nbsp;&nbsp;</CODE></TD>
1319<TD>relevant functions:</TD>
1320</TR>
1321<TR>
1322<TD><CODE>_round_to_zero</CODE></TD>
1323<TD><CODE>_r_minMag</CODE></TD>
1324<TD>conversions from floating-point to integer (<NOBR>section 8.2</NOBR>)</TD>
1325</TR>
1326<TR>
1327<TD><CODE>round_to_int</CODE></TD>
1328<TD><CODE>roundToInt</CODE></TD>
1329<TD>round-to-integer functions (<NOBR>section 8.7</NOBR>)</TD>
1330</TR>
1331<TR>
1332<TD><CODE>is_signaling_nan&nbsp;&nbsp;&nbsp;&nbsp;</CODE></TD>
1333<TD><CODE>isSignalingNaN</CODE></TD>
1334<TD>signaling NaN test functions (<NOBR>section 8.9</NOBR>)</TD>
1335</TR>
1336</TABLE>
1337</BLOCKQUOTE>
1338</P>
1339
1340<H3>9.2. Changes to Function Arguments</H3>
1341
1342<P>
1343Besides simple name changes, some operations were given a different interface
1344in <NOBR>Release 3</NOBR> than they had in <NOBR>Release 2</NOBR>:
1345<UL>
1346
1347<LI>
1348<P>
1349Since <NOBR>Release 3</NOBR>, integer arguments and results of functions have
1350standard types from header <CODE>&lt;stdint.h&gt;</CODE>, such as
1351<CODE>uint32_t</CODE>, whereas previously their types could be defined
1352differently for each port of SoftFloat, usually using traditional C types such
1353as <CODE>unsigned</CODE> <CODE>int</CODE>.
1354Likewise, functions in <NOBR>Release 3</NOBR> and later pass Booleans as
1355standard type <CODE>bool</CODE> from <CODE>&lt;stdbool.h&gt;</CODE>, whereas
1356previously these were again passed as a port-specific type (usually
1357<CODE>int</CODE>).
1358</P>
1359
1360<LI>
1361<P>
1362As explained earlier in <NOBR>section 4.5</NOBR>, <I>Conventions for Passing
1363Arguments and Results</I>, SoftFloat functions in <NOBR>Release 3</NOBR> and
1364later may pass <NOBR>80-bit</NOBR> and <NOBR>128-bit</NOBR> floating-point
1365values through pointers, meaning that functions take pointer arguments and then
1366read or write floating-point values at the locations indicated by the pointers.
1367In <NOBR>Release 2</NOBR>, floating-point arguments and results were always
1368passed by value, regardless of their size.
1369</P>
1370
1371<LI>
1372<P>
1373Functions that round to an integer have additional
1374<CODE><I>roundingMode</I></CODE> and <CODE><I>exact</I></CODE> arguments that
1375they did not have in <NOBR>Release 2</NOBR>.
1376Refer to sections 8.2 <NOBR>and 8.7</NOBR> for descriptions of these functions
1377since <NOBR>Release 3</NOBR>.
1378For <NOBR>Release 2</NOBR>, the rounding mode, when needed, was taken from the
1379same global variable that affects the basic arithmetic operations (now called
1380<CODE>softfloat_roundingMode</CODE> but previously known as
1381<CODE>float_rounding_mode</CODE>).
1382Also, for <NOBR>Release 2</NOBR>, if the original floating-point input was not
1383an exact integer value, and if the <I>invalid</I> exception was not raised by
1384the function, the <I>inexact</I> exception was always raised.
1385<NOBR>Release 2</NOBR> had no option to suppress raising <I>inexact</I> in this
1386case.
1387Applications using SoftFloat <NOBR>Release 3</NOBR> or later can get the same
1388effect as <NOBR>Release 2</NOBR> by passing variable
1389<CODE>softfloat_roundingMode</CODE> for argument
1390<CODE><I>roundingMode</I></CODE> and <CODE>true</CODE> for argument
1391<CODE><I>exact</I></CODE>.
1392</P>
1393
1394</UL>
1395</P>
1396
1397<H3>9.3. Added Capabilities</H3>
1398
1399<P>
1400With <NOBR>Release 3</NOBR>, some new features have been added that were not
1401present in <NOBR>Release 2</NOBR>:
1402<UL>
1403
1404<LI>
1405<P>
1406A port of SoftFloat can now define any of the floating-point types
1407<CODE>float32_t</CODE>, <CODE>float64_t</CODE>, <CODE>extFloat80_t</CODE>, and
1408<CODE>float128_t</CODE> as aliases for C&rsquo;s standard floating-point types
1409<CODE>float</CODE>, <CODE>double</CODE>, and <CODE>long</CODE>
1410<CODE>double</CODE>, using either <CODE>#define</CODE> or <CODE>typedef</CODE>.
1411This potential convenience was not supported under <NOBR>Release 2</NOBR>.
1412</P>
1413
1414<P>
1415(Note, however, that there may be a performance cost to defining
1416SoftFloat&rsquo;s floating-point types this way, depending on the platform and
1417the applications using SoftFloat.
1418Ports of SoftFloat may choose to forgo the convenience in favor of better
1419speed.)
1420</P>
1421
1422<P>
1423<LI>
1424As of <NOBR>Release 3b</NOBR>, <NOBR>16-bit</NOBR> half-precision,
1425<CODE>float16_t</CODE>, is supported.
1426</P>
1427
1428<P>
1429<LI>
1430Functions have been added for converting between the floating-point types and
1431unsigned integers.
1432<NOBR>Release 2</NOBR> supported only signed integers, not unsigned.
1433</P>
1434
1435<P>
1436<LI>
1437Fused multiply-add functions have been added for all floating-point formats
1438except <NOBR>80-bit</NOBR> double-extended-precision,
1439<CODE>extFloat80_t</CODE>.
1440</P>
1441
1442<P>
1443<LI>
1444New rounding modes are supported:
1445<CODE>softfloat_round_near_maxMag</CODE> (round to nearest, with ties to
1446maximum magnitude, away from zero), and, as of <NOBR>Release 3c</NOBR>,
1447optional <CODE>softfloat_round_odd</CODE> (round to odd, also known as
1448jamming).
1449</P>
1450
1451</UL>
1452</P>
1453
1454<H3>9.4. Better Compatibility with the C Language</H3>
1455
1456<P>
1457<NOBR>Release 3</NOBR> of SoftFloat was written to conform better to the ISO C
1458Standard&rsquo;s rules for portability.
1459For example, older releases of SoftFloat employed type conversions in ways
1460that, while commonly practiced, are not fully defined by the C Standard.
1461Such problematic type conversions have generally been replaced by the use of
1462unions, the behavior around which is more strictly regulated these days.
1463</P>
1464
1465<H3>9.5. New Organization as a Library</H3>
1466
1467<P>
1468Starting with <NOBR>Release 3</NOBR>, SoftFloat now builds as a library.
1469Previously, SoftFloat compiled into a single, monolithic object file containing
1470all the SoftFloat functions, with the consequence that a program linking with
1471SoftFloat would get every SoftFloat function in its binary file even if only a
1472few functions were actually used.
1473With SoftFloat in the form of a library, a program that is linked by a standard
1474linker will include only those functions of SoftFloat that it needs and no
1475others.
1476</P>
1477
1478<H3>9.6. Optimization Gains (and Losses)</H3>
1479
1480<P>
1481Individual SoftFloat functions have been variously improved in
1482<NOBR>Release 3</NOBR> compared to earlier releases.
1483In particular, better, faster algorithms have been deployed for the operations
1484of division, square root, and remainder.
1485For functions operating on the larger <NOBR>80-bit</NOBR> and
1486<NOBR>128-bit</NOBR> formats, <CODE>extFloat80_t</CODE> and
1487<CODE>float128_t</CODE>, code size has also generally been reduced.
1488</P>
1489
1490<P>
1491However, because <NOBR>Release 2</NOBR> compiled all of SoftFloat together as a
1492single object file, compilers could make optimizations across function calls
1493when one SoftFloat function calls another.
1494Now that the functions of SoftFloat are compiled separately and only afterward
1495linked together into a program, there is not usually the same opportunity to
1496optimize across function calls.
1497Some loss of speed has been observed due to this change.
1498</P>
1499
1500
1501<H2>10. Future Directions</H2>
1502
1503<P>
1504The following improvements are anticipated for future releases of SoftFloat:
1505<UL>
1506<LI>
1507more functions from the 2008 version of the IEEE Floating-Point Standard;
1508<LI>
1509consistent, defined behavior for non-canonical representations of extended
1510format <CODE>extFloat80_t</CODE> (discussed in <NOBR>section 4.4</NOBR>,
1511<I>Non-canonical Representations in <CODE>extFloat80_t</CODE></I>).
1512
1513</UL>
1514</P>
1515
1516
1517<H2>11. Contact Information</H2>
1518
1519<P>
1520At the time of this writing, the most up-to-date information about SoftFloat
1521and the latest release can be found at the Web page
1522<A HREF="http://www.jhauser.us/arithmetic/SoftFloat.html"><NOBR><CODE>http://www.jhauser.us/arithmetic/SoftFloat.html</CODE></NOBR></A>.
1523</P>
1524
1525
1526</BODY>
1527
deps/SoftFloat-3e/source/8086-SSE/extF80M_isSignalingNaN.c deleted-57
...@@ -1,57 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43*----------------------------------------------------------------------------*/
44bool extF80M_isSignalingNaN( const extFloat80_t *aPtr )
45{
46 const struct extFloat80M *aSPtr;
47 uint64_t uiA0;
48
49 aSPtr = (const struct extFloat80M *) aPtr;
50 if ( (aSPtr->signExp & 0x7FFF) != 0x7FFF ) return false;
51 uiA0 = aSPtr->signif;
52 return
53 ! (uiA0 & UINT64_C( 0x4000000000000000 ))
54 && (uiA0 & UINT64_C( 0x3FFFFFFFFFFFFFFF));
55
56}
57
deps/SoftFloat-3e/source/8086-SSE/f128M_isSignalingNaN.c deleted-60
...@@ -1,60 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "primitives.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44*----------------------------------------------------------------------------*/
45bool f128M_isSignalingNaN( const float128_t *aPtr )
46{
47 const uint32_t *aWPtr;
48 uint32_t uiA96;
49
50 aWPtr = (const uint32_t *) aPtr;
51 uiA96 = aWPtr[indexWordHi( 4 )];
52 if ( (uiA96 & 0x7FFF8000) != 0x7FFF0000 ) return false;
53 return
54 ((uiA96 & 0x00007FFF) != 0)
55 || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
56 | aWPtr[indexWord( 4, 0 )])
57 != 0);
58
59}
60
deps/SoftFloat-3e/source/8086-SSE/s_commonNaNToExtF80M.c deleted-56
...@@ -1,56 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "specialize.h"
41
42/*----------------------------------------------------------------------------
43| Converts the common NaN pointed to by `aPtr' into an 80-bit extended
44| floating-point NaN, and stores this NaN at the location pointed to by
45| `zSPtr'.
46*----------------------------------------------------------------------------*/
47void
48 softfloat_commonNaNToExtF80M(
49 const struct commonNaN *aPtr, struct extFloat80M *zSPtr )
50{
51
52 zSPtr->signExp = packToExtF80UI64( aPtr->sign, 0x7FFF );
53 zSPtr->signif = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1;
54
55}
56
deps/SoftFloat-3e/source/8086-SSE/s_commonNaNToExtF80UI.c deleted-56
...@@ -1,56 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41
42/*----------------------------------------------------------------------------
43| Converts the common NaN pointed to by `aPtr' into an 80-bit extended
44| floating-point NaN, and returns the bit pattern of this value as an unsigned
45| integer.
46*----------------------------------------------------------------------------*/
47struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr )
48{
49 struct uint128 uiZ;
50
51 uiZ.v64 = (uint_fast16_t) aPtr->sign<<15 | 0x7FFF;
52 uiZ.v0 = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1;
53 return uiZ;
54
55}
56
deps/SoftFloat-3e/source/8086-SSE/s_commonNaNToF128M.c deleted-56
...@@ -1,56 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41
42/*----------------------------------------------------------------------------
43| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point
44| NaN, and stores this NaN at the location pointed to by `zWPtr'. Argument
45| `zWPtr' points to an array of four 32-bit elements that concatenate in the
46| platform's normal endian order to form a 128-bit floating-point value.
47*----------------------------------------------------------------------------*/
48void
49 softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr )
50{
51
52 softfloat_shortShiftRight128M( (const uint32_t *) &aPtr->v0, 16, zWPtr );
53 zWPtr[indexWordHi( 4 )] |= (uint32_t) aPtr->sign<<31 | 0x7FFF8000;
54
55}
56
deps/SoftFloat-3e/source/8086-SSE/s_commonNaNToF128UI.c deleted-55
...@@ -1,55 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41
42/*----------------------------------------------------------------------------
43| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point
44| NaN, and returns the bit pattern of this value as an unsigned integer.
45*----------------------------------------------------------------------------*/
46struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
47{
48 struct uint128 uiZ;
49
50 uiZ = softfloat_shortShiftRight128( aPtr->v64, aPtr->v0, 16 );
51 uiZ.v64 |= (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FFF800000000000 );
52 return uiZ;
53
54}
55
deps/SoftFloat-3e/source/8086-SSE/s_commonNaNToF16UI.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40
41/*----------------------------------------------------------------------------
42| Converts the common NaN pointed to by `aPtr' into a 16-bit floating-point
43| NaN, and returns the bit pattern of this value as an unsigned integer.
44*----------------------------------------------------------------------------*/
45uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr )
46{
47
48 return (uint_fast16_t) aPtr->sign<<15 | 0x7E00 | aPtr->v64>>54;
49
50}
51
deps/SoftFloat-3e/source/8086-SSE/s_commonNaNToF32UI.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40
41/*----------------------------------------------------------------------------
42| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point
43| NaN, and returns the bit pattern of this value as an unsigned integer.
44*----------------------------------------------------------------------------*/
45uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr )
46{
47
48 return (uint_fast32_t) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41;
49
50}
51
deps/SoftFloat-3e/source/8086-SSE/s_commonNaNToF64UI.c deleted-53
...@@ -1,53 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40
41/*----------------------------------------------------------------------------
42| Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point
43| NaN, and returns the bit pattern of this value as an unsigned integer.
44*----------------------------------------------------------------------------*/
45uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr )
46{
47
48 return
49 (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FF8000000000000 )
50 | aPtr->v64>>12;
51
52}
53
deps/SoftFloat-3e/source/8086-SSE/s_extF80MToCommonNaN.c deleted-62
...@@ -1,62 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44| Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is
45| a NaN, converts this NaN to the common NaN form, and stores the resulting
46| common NaN at the location pointed to by `zPtr'. If the NaN is a signaling
47| NaN, the invalid exception is raised.
48*----------------------------------------------------------------------------*/
49void
50 softfloat_extF80MToCommonNaN(
51 const struct extFloat80M *aSPtr, struct commonNaN *zPtr )
52{
53
54 if ( extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ) ) {
55 softfloat_raiseFlags( softfloat_flag_invalid );
56 }
57 zPtr->sign = signExtF80UI64( aSPtr->signExp );
58 zPtr->v64 = aSPtr->signif<<1;
59 zPtr->v0 = 0;
60
61}
62
deps/SoftFloat-3e/source/8086-SSE/s_extF80UIToCommonNaN.c deleted-62
...@@ -1,62 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0'
44| has the bit pattern of an 80-bit extended floating-point NaN, converts
45| this NaN to the common NaN form, and stores the resulting common NaN at the
46| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
47| exception is raised.
48*----------------------------------------------------------------------------*/
49void
50 softfloat_extF80UIToCommonNaN(
51 uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr )
52{
53
54 if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ) {
55 softfloat_raiseFlags( softfloat_flag_invalid );
56 }
57 zPtr->sign = uiA64>>15;
58 zPtr->v64 = uiA0<<1;
59 zPtr->v0 = 0;
60
61}
62
deps/SoftFloat-3e/source/8086-SSE/s_f128MToCommonNaN.c deleted-62
...@@ -1,62 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44| Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN,
45| converts this NaN to the common NaN form, and stores the resulting common
46| NaN at the location pointed to by `zPtr'. If the NaN is a signaling NaN,
47| the invalid exception is raised. Argument `aWPtr' points to an array of
48| four 32-bit elements that concatenate in the platform's normal endian order
49| to form a 128-bit floating-point value.
50*----------------------------------------------------------------------------*/
51void
52 softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr )
53{
54
55 if ( f128M_isSignalingNaN( (const float128_t *) aWPtr ) ) {
56 softfloat_raiseFlags( softfloat_flag_invalid );
57 }
58 zPtr->sign = aWPtr[indexWordHi( 4 )]>>31;
59 softfloat_shortShiftLeft128M( aWPtr, 16, (uint32_t *) &zPtr->v0 );
60
61}
62
deps/SoftFloat-3e/source/8086-SSE/s_f128UIToCommonNaN.c deleted-65
...@@ -1,65 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0'
45| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to
46| the common NaN form, and stores the resulting common NaN at the location
47| pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception
48| is raised.
49*----------------------------------------------------------------------------*/
50void
51 softfloat_f128UIToCommonNaN(
52 uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr )
53{
54 struct uint128 NaNSig;
55
56 if ( softfloat_isSigNaNF128UI( uiA64, uiA0 ) ) {
57 softfloat_raiseFlags( softfloat_flag_invalid );
58 }
59 NaNSig = softfloat_shortShiftLeft128( uiA64, uiA0, 16 );
60 zPtr->sign = uiA64>>63;
61 zPtr->v64 = NaNSig.v64;
62 zPtr->v0 = NaNSig.v0;
63
64}
65
deps/SoftFloat-3e/source/8086-SSE/s_f16UIToCommonNaN.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Assuming `uiA' has the bit pattern of a 16-bit floating-point NaN, converts
44| this NaN to the common NaN form, and stores the resulting common NaN at the
45| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
46| exception is raised.
47*----------------------------------------------------------------------------*/
48void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr )
49{
50
51 if ( softfloat_isSigNaNF16UI( uiA ) ) {
52 softfloat_raiseFlags( softfloat_flag_invalid );
53 }
54 zPtr->sign = uiA>>15;
55 zPtr->v64 = (uint_fast64_t) uiA<<54;
56 zPtr->v0 = 0;
57
58}
59
deps/SoftFloat-3e/source/8086-SSE/s_f32UIToCommonNaN.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts
44| this NaN to the common NaN form, and stores the resulting common NaN at the
45| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
46| exception is raised.
47*----------------------------------------------------------------------------*/
48void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr )
49{
50
51 if ( softfloat_isSigNaNF32UI( uiA ) ) {
52 softfloat_raiseFlags( softfloat_flag_invalid );
53 }
54 zPtr->sign = uiA>>31;
55 zPtr->v64 = (uint_fast64_t) uiA<<41;
56 zPtr->v0 = 0;
57
58}
59
deps/SoftFloat-3e/source/8086-SSE/s_f64UIToCommonNaN.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts
44| this NaN to the common NaN form, and stores the resulting common NaN at the
45| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
46| exception is raised.
47*----------------------------------------------------------------------------*/
48void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr )
49{
50
51 if ( softfloat_isSigNaNF64UI( uiA ) ) {
52 softfloat_raiseFlags( softfloat_flag_invalid );
53 }
54 zPtr->sign = uiA>>63;
55 zPtr->v64 = uiA<<12;
56 zPtr->v0 = 0;
57
58}
59
deps/SoftFloat-3e/source/8086-SSE/s_propagateNaNExtF80M.c deleted-107
...@@ -1,107 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Assuming at least one of the two 80-bit extended floating-point values
46| pointed to by `aSPtr' and `bSPtr' is a NaN, stores the combined NaN result
47| at the location pointed to by `zSPtr'. If either original floating-point
48| value is a signaling NaN, the invalid exception is raised.
49*----------------------------------------------------------------------------*/
50void
51 softfloat_propagateNaNExtF80M(
52 const struct extFloat80M *aSPtr,
53 const struct extFloat80M *bSPtr,
54 struct extFloat80M *zSPtr
55 )
56{
57 bool isSigNaNA;
58 const struct extFloat80M *sPtr;
59 bool isSigNaNB;
60 uint_fast16_t uiB64;
61 uint64_t uiB0;
62 uint_fast16_t uiA64;
63 uint64_t uiA0;
64 uint_fast16_t uiMagA64, uiMagB64;
65
66 isSigNaNA = extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr );
67 sPtr = aSPtr;
68 if ( ! bSPtr ) {
69 if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid );
70 goto copy;
71 }
72 isSigNaNB = extF80M_isSignalingNaN( (const extFloat80_t *) bSPtr );
73 if ( isSigNaNA | isSigNaNB ) {
74 softfloat_raiseFlags( softfloat_flag_invalid );
75 if ( isSigNaNA ) {
76 uiB64 = bSPtr->signExp;
77 if ( isSigNaNB ) goto returnLargerUIMag;
78 uiB0 = bSPtr->signif;
79 if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto copyB;
80 goto copy;
81 } else {
82 uiA64 = aSPtr->signExp;
83 uiA0 = aSPtr->signif;
84 if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto copy;
85 goto copyB;
86 }
87 }
88 uiB64 = bSPtr->signExp;
89 returnLargerUIMag:
90 uiA64 = aSPtr->signExp;
91 uiMagA64 = uiA64 & 0x7FFF;
92 uiMagB64 = uiB64 & 0x7FFF;
93 if ( uiMagA64 < uiMagB64 ) goto copyB;
94 if ( uiMagB64 < uiMagA64 ) goto copy;
95 uiA0 = aSPtr->signif;
96 uiB0 = bSPtr->signif;
97 if ( uiA0 < uiB0 ) goto copyB;
98 if ( uiB0 < uiA0 ) goto copy;
99 if ( uiA64 < uiB64 ) goto copy;
100 copyB:
101 sPtr = bSPtr;
102 copy:
103 zSPtr->signExp = sPtr->signExp;
104 zSPtr->signif = sPtr->signif | UINT64_C( 0xC000000000000000 );
105
106}
107
deps/SoftFloat-3e/source/8086-SSE/s_propagateNaNExtF80UI.c deleted-106
...@@ -1,106 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2018 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting the unsigned integer formed from concatenating 'uiA64' and
46| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting
47| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
48| 80-bit extended floating-point value, and assuming at least on of these
49| floating-point values is a NaN, returns the bit pattern of the combined NaN
50| result. If either original floating-point value is a signaling NaN, the
51| invalid exception is raised.
52*----------------------------------------------------------------------------*/
53struct uint128
54 softfloat_propagateNaNExtF80UI(
55 uint_fast16_t uiA64,
56 uint_fast64_t uiA0,
57 uint_fast16_t uiB64,
58 uint_fast64_t uiB0
59 )
60{
61 bool isSigNaNA, isSigNaNB;
62 uint_fast64_t uiNonsigA0, uiNonsigB0;
63 uint_fast16_t uiMagA64, uiMagB64;
64 struct uint128 uiZ;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 isSigNaNA = softfloat_isSigNaNExtF80UI( uiA64, uiA0 );
69 isSigNaNB = softfloat_isSigNaNExtF80UI( uiB64, uiB0 );
70 /*------------------------------------------------------------------------
71 | Make NaNs non-signaling.
72 *------------------------------------------------------------------------*/
73 uiNonsigA0 = uiA0 | UINT64_C( 0xC000000000000000 );
74 uiNonsigB0 = uiB0 | UINT64_C( 0xC000000000000000 );
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 if ( isSigNaNA | isSigNaNB ) {
78 softfloat_raiseFlags( softfloat_flag_invalid );
79 if ( isSigNaNA ) {
80 if ( isSigNaNB ) goto returnLargerMag;
81 if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto returnB;
82 goto returnA;
83 } else {
84 if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto returnA;
85 goto returnB;
86 }
87 }
88 returnLargerMag:
89 uiMagA64 = uiA64 & 0x7FFF;
90 uiMagB64 = uiB64 & 0x7FFF;
91 if ( uiMagA64 < uiMagB64 ) goto returnB;
92 if ( uiMagB64 < uiMagA64 ) goto returnA;
93 if ( uiA0 < uiB0 ) goto returnB;
94 if ( uiB0 < uiA0 ) goto returnA;
95 if ( uiA64 < uiB64 ) goto returnA;
96 returnB:
97 uiZ.v64 = uiB64;
98 uiZ.v0 = uiNonsigB0;
99 return uiZ;
100 returnA:
101 uiZ.v64 = uiA64;
102 uiZ.v0 = uiNonsigA0;
103 return uiZ;
104
105}
106
deps/SoftFloat-3e/source/8086-SSE/s_propagateNaNF128M.c deleted-76
...@@ -1,76 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Assuming at least one of the two 128-bit floating-point values pointed to by
46| `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location
47| pointed to by `zWPtr'. If either original floating-point value is a
48| signaling NaN, the invalid exception is raised. Each of `aWPtr', `bWPtr',
49| and `zWPtr' points to an array of four 32-bit elements that concatenate in
50| the platform's normal endian order to form a 128-bit floating-point value.
51*----------------------------------------------------------------------------*/
52void
53 softfloat_propagateNaNF128M(
54 const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr )
55{
56 bool isSigNaNA;
57 const uint32_t *ptr;
58
59 ptr = aWPtr;
60 isSigNaNA = f128M_isSignalingNaN( (const float128_t *) aWPtr );
61 if (
62 isSigNaNA
63 || (bWPtr && f128M_isSignalingNaN( (const float128_t *) bWPtr ))
64 ) {
65 softfloat_raiseFlags( softfloat_flag_invalid );
66 if ( isSigNaNA ) goto copy;
67 }
68 if ( ! softfloat_isNaNF128M( aWPtr ) ) ptr = bWPtr;
69 copy:
70 zWPtr[indexWordHi( 4 )] = ptr[indexWordHi( 4 )] | 0x00008000;
71 zWPtr[indexWord( 4, 2 )] = ptr[indexWord( 4, 2 )];
72 zWPtr[indexWord( 4, 1 )] = ptr[indexWord( 4, 1 )];
73 zWPtr[indexWord( 4, 0 )] = ptr[indexWord( 4, 0 )];
74
75}
76
deps/SoftFloat-3e/source/8086-SSE/s_propagateNaNF128UI.c deleted-81
...@@ -1,81 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting the unsigned integer formed from concatenating `uiA64' and
46| `uiA0' as a 128-bit floating-point value, and likewise interpreting the
47| unsigned integer formed from concatenating `uiB64' and `uiB0' as another
48| 128-bit floating-point value, and assuming at least on of these floating-
49| point values is a NaN, returns the bit pattern of the combined NaN result.
50| If either original floating-point value is a signaling NaN, the invalid
51| exception is raised.
52*----------------------------------------------------------------------------*/
53struct uint128
54 softfloat_propagateNaNF128UI(
55 uint_fast64_t uiA64,
56 uint_fast64_t uiA0,
57 uint_fast64_t uiB64,
58 uint_fast64_t uiB0
59 )
60{
61 bool isSigNaNA;
62 struct uint128 uiZ;
63
64 isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 );
65 if ( isSigNaNA || softfloat_isSigNaNF128UI( uiB64, uiB0 ) ) {
66 softfloat_raiseFlags( softfloat_flag_invalid );
67 if ( isSigNaNA ) goto returnNonsigA;
68 }
69 if ( isNaNF128UI( uiA64, uiA0 ) ) {
70 returnNonsigA:
71 uiZ.v64 = uiA64;
72 uiZ.v0 = uiA0;
73 } else {
74 uiZ.v64 = uiB64;
75 uiZ.v0 = uiB0;
76 }
77 uiZ.v64 |= UINT64_C( 0x0000800000000000 );
78 return uiZ;
79
80}
81
deps/SoftFloat-3e/source/8086-SSE/s_propagateNaNF16UI.c deleted-63
...@@ -1,63 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting `uiA' and `uiB' as the bit patterns of two 16-bit floating-
46| point values, at least one of which is a NaN, returns the bit pattern of
47| the combined NaN result. If either `uiA' or `uiB' has the pattern of a
48| signaling NaN, the invalid exception is raised.
49*----------------------------------------------------------------------------*/
50uint_fast16_t
51 softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB )
52{
53 bool isSigNaNA;
54
55 isSigNaNA = softfloat_isSigNaNF16UI( uiA );
56 if ( isSigNaNA || softfloat_isSigNaNF16UI( uiB ) ) {
57 softfloat_raiseFlags( softfloat_flag_invalid );
58 if ( isSigNaNA ) return uiA | 0x0200;
59 }
60 return (isNaNF16UI( uiA ) ? uiA : uiB) | 0x0200;
61
62}
63
deps/SoftFloat-3e/source/8086-SSE/s_propagateNaNF32UI.c deleted-63
...@@ -1,63 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating-
46| point values, at least one of which is a NaN, returns the bit pattern of
47| the combined NaN result. If either `uiA' or `uiB' has the pattern of a
48| signaling NaN, the invalid exception is raised.
49*----------------------------------------------------------------------------*/
50uint_fast32_t
51 softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB )
52{
53 bool isSigNaNA;
54
55 isSigNaNA = softfloat_isSigNaNF32UI( uiA );
56 if ( isSigNaNA || softfloat_isSigNaNF32UI( uiB ) ) {
57 softfloat_raiseFlags( softfloat_flag_invalid );
58 if ( isSigNaNA ) return uiA | 0x00400000;
59 }
60 return (isNaNF32UI( uiA ) ? uiA : uiB) | 0x00400000;
61
62}
63
deps/SoftFloat-3e/source/8086-SSE/s_propagateNaNF64UI.c deleted-63
...@@ -1,63 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating-
46| point values, at least one of which is a NaN, returns the bit pattern of
47| the combined NaN result. If either `uiA' or `uiB' has the pattern of a
48| signaling NaN, the invalid exception is raised.
49*----------------------------------------------------------------------------*/
50uint_fast64_t
51 softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB )
52{
53 bool isSigNaNA;
54
55 isSigNaNA = softfloat_isSigNaNF64UI( uiA );
56 if ( isSigNaNA || softfloat_isSigNaNF64UI( uiB ) ) {
57 softfloat_raiseFlags( softfloat_flag_invalid );
58 if ( isSigNaNA ) return uiA | UINT64_C( 0x0008000000000000 );
59 }
60 return (isNaNF64UI( uiA ) ? uiA : uiB) | UINT64_C( 0x0008000000000000 );
61
62}
63
deps/SoftFloat-3e/source/8086-SSE/softfloat_raiseFlags.c deleted-52
...@@ -1,52 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include "platform.h"
38#include "softfloat.h"
39
40/*----------------------------------------------------------------------------
41| Raises the exceptions specified by `flags'. Floating-point traps can be
42| defined here if desired. It is currently not possible for such a trap
43| to substitute a result value. If traps are not implemented, this routine
44| should be simply `softfloat_exceptionFlags |= flags;'.
45*----------------------------------------------------------------------------*/
46void softfloat_raiseFlags( uint_fast8_t flags )
47{
48
49 softfloat_exceptionFlags |= flags;
50
51}
52
deps/SoftFloat-3e/source/8086-SSE/specialize.h deleted-376
...@@ -1,376 +0,0 @@
1
2/*============================================================================
3
4This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2018 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#ifndef specialize_h
38#define specialize_h 1
39
40#include <stdbool.h>
41#include <stdint.h>
42#include "primitiveTypes.h"
43#include "softfloat.h"
44
45/*----------------------------------------------------------------------------
46| Default value for 'softfloat_detectTininess'.
47*----------------------------------------------------------------------------*/
48#define init_detectTininess softfloat_tininess_afterRounding
49
50/*----------------------------------------------------------------------------
51| The values to return on conversions to 32-bit integer formats that raise an
52| invalid exception.
53*----------------------------------------------------------------------------*/
54#define ui32_fromPosOverflow 0xFFFFFFFF
55#define ui32_fromNegOverflow 0xFFFFFFFF
56#define ui32_fromNaN 0xFFFFFFFF
57#define i32_fromPosOverflow (-0x7FFFFFFF - 1)
58#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
59#define i32_fromNaN (-0x7FFFFFFF - 1)
60
61/*----------------------------------------------------------------------------
62| The values to return on conversions to 64-bit integer formats that raise an
63| invalid exception.
64*----------------------------------------------------------------------------*/
65#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
66#define ui64_fromNegOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
67#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF )
68#define i64_fromPosOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
69#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
70#define i64_fromNaN (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
71
72/*----------------------------------------------------------------------------
73| "Common NaN" structure, used to transfer NaN representations from one format
74| to another.
75*----------------------------------------------------------------------------*/
76struct commonNaN {
77 bool sign;
78#ifdef LITTLEENDIAN
79 uint64_t v0, v64;
80#else
81 uint64_t v64, v0;
82#endif
83};
84
85/*----------------------------------------------------------------------------
86| The bit pattern for a default generated 16-bit floating-point NaN.
87*----------------------------------------------------------------------------*/
88#define defaultNaNF16UI 0xFE00
89
90/*----------------------------------------------------------------------------
91| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a
92| 16-bit floating-point signaling NaN.
93| Note: This macro evaluates its argument more than once.
94*----------------------------------------------------------------------------*/
95#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF))
96
97/*----------------------------------------------------------------------------
98| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts
99| this NaN to the common NaN form, and stores the resulting common NaN at the
100| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
101| exception is raised.
102*----------------------------------------------------------------------------*/
103void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr );
104
105/*----------------------------------------------------------------------------
106| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
107| NaN, and returns the bit pattern of this value as an unsigned integer.
108*----------------------------------------------------------------------------*/
109uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
110
111/*----------------------------------------------------------------------------
112| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
113| point values, at least one of which is a NaN, returns the bit pattern of
114| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
115| signaling NaN, the invalid exception is raised.
116*----------------------------------------------------------------------------*/
117uint_fast16_t
118 softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
119
120/*----------------------------------------------------------------------------
121| The bit pattern for a default generated 32-bit floating-point NaN.
122*----------------------------------------------------------------------------*/
123#define defaultNaNF32UI 0xFFC00000
124
125/*----------------------------------------------------------------------------
126| Returns true when 32-bit unsigned integer 'uiA' has the bit pattern of a
127| 32-bit floating-point signaling NaN.
128| Note: This macro evaluates its argument more than once.
129*----------------------------------------------------------------------------*/
130#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF))
131
132/*----------------------------------------------------------------------------
133| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts
134| this NaN to the common NaN form, and stores the resulting common NaN at the
135| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
136| exception is raised.
137*----------------------------------------------------------------------------*/
138void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr );
139
140/*----------------------------------------------------------------------------
141| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point
142| NaN, and returns the bit pattern of this value as an unsigned integer.
143*----------------------------------------------------------------------------*/
144uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
145
146/*----------------------------------------------------------------------------
147| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
148| point values, at least one of which is a NaN, returns the bit pattern of
149| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
150| signaling NaN, the invalid exception is raised.
151*----------------------------------------------------------------------------*/
152uint_fast32_t
153 softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
154
155/*----------------------------------------------------------------------------
156| The bit pattern for a default generated 64-bit floating-point NaN.
157*----------------------------------------------------------------------------*/
158#define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 )
159
160/*----------------------------------------------------------------------------
161| Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a
162| 64-bit floating-point signaling NaN.
163| Note: This macro evaluates its argument more than once.
164*----------------------------------------------------------------------------*/
165#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF )))
166
167/*----------------------------------------------------------------------------
168| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
169| this NaN to the common NaN form, and stores the resulting common NaN at the
170| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
171| exception is raised.
172*----------------------------------------------------------------------------*/
173void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr );
174
175/*----------------------------------------------------------------------------
176| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point
177| NaN, and returns the bit pattern of this value as an unsigned integer.
178*----------------------------------------------------------------------------*/
179uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
180
181/*----------------------------------------------------------------------------
182| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
183| point values, at least one of which is a NaN, returns the bit pattern of
184| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
185| signaling NaN, the invalid exception is raised.
186*----------------------------------------------------------------------------*/
187uint_fast64_t
188 softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
189
190/*----------------------------------------------------------------------------
191| The bit pattern for a default generated 80-bit extended floating-point NaN.
192*----------------------------------------------------------------------------*/
193#define defaultNaNExtF80UI64 0xFFFF
194#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 )
195
196/*----------------------------------------------------------------------------
197| Returns true when the 80-bit unsigned integer formed from concatenating
198| 16-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of an 80-bit extended
199| floating-point signaling NaN.
200| Note: This macro evaluates its arguments more than once.
201*----------------------------------------------------------------------------*/
202#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
203
204#ifdef SOFTFLOAT_FAST_INT64
205
206/*----------------------------------------------------------------------------
207| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is
208| defined.
209*----------------------------------------------------------------------------*/
210
211/*----------------------------------------------------------------------------
212| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
213| has the bit pattern of an 80-bit extended floating-point NaN, converts
214| this NaN to the common NaN form, and stores the resulting common NaN at the
215| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
216| exception is raised.
217*----------------------------------------------------------------------------*/
218void
219 softfloat_extF80UIToCommonNaN(
220 uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
221
222/*----------------------------------------------------------------------------
223| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
224| floating-point NaN, and returns the bit pattern of this value as an unsigned
225| integer.
226*----------------------------------------------------------------------------*/
227struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
228
229/*----------------------------------------------------------------------------
230| Interpreting the unsigned integer formed from concatenating 'uiA64' and
231| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting
232| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
233| 80-bit extended floating-point value, and assuming at least on of these
234| floating-point values is a NaN, returns the bit pattern of the combined NaN
235| result. If either original floating-point value is a signaling NaN, the
236| invalid exception is raised.
237*----------------------------------------------------------------------------*/
238struct uint128
239 softfloat_propagateNaNExtF80UI(
240 uint_fast16_t uiA64,
241 uint_fast64_t uiA0,
242 uint_fast16_t uiB64,
243 uint_fast64_t uiB0
244 );
245
246/*----------------------------------------------------------------------------
247| The bit pattern for a default generated 128-bit floating-point NaN.
248*----------------------------------------------------------------------------*/
249#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 )
250#define defaultNaNF128UI0 UINT64_C( 0 )
251
252/*----------------------------------------------------------------------------
253| Returns true when the 128-bit unsigned integer formed from concatenating
254| 64-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of a 128-bit floating-
255| point signaling NaN.
256| Note: This macro evaluates its arguments more than once.
257*----------------------------------------------------------------------------*/
258#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
259
260/*----------------------------------------------------------------------------
261| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
262| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to
263| the common NaN form, and stores the resulting common NaN at the location
264| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
265| is raised.
266*----------------------------------------------------------------------------*/
267void
268 softfloat_f128UIToCommonNaN(
269 uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
270
271/*----------------------------------------------------------------------------
272| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
273| NaN, and returns the bit pattern of this value as an unsigned integer.
274*----------------------------------------------------------------------------*/
275struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
276
277/*----------------------------------------------------------------------------
278| Interpreting the unsigned integer formed from concatenating 'uiA64' and
279| 'uiA0' as a 128-bit floating-point value, and likewise interpreting the
280| unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
281| 128-bit floating-point value, and assuming at least on of these floating-
282| point values is a NaN, returns the bit pattern of the combined NaN result.
283| If either original floating-point value is a signaling NaN, the invalid
284| exception is raised.
285*----------------------------------------------------------------------------*/
286struct uint128
287 softfloat_propagateNaNF128UI(
288 uint_fast64_t uiA64,
289 uint_fast64_t uiA0,
290 uint_fast64_t uiB64,
291 uint_fast64_t uiB0
292 );
293
294#else
295
296/*----------------------------------------------------------------------------
297| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is not
298| defined.
299*----------------------------------------------------------------------------*/
300
301/*----------------------------------------------------------------------------
302| Assuming the 80-bit extended floating-point value pointed to by 'aSPtr' is
303| a NaN, converts this NaN to the common NaN form, and stores the resulting
304| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
305| NaN, the invalid exception is raised.
306*----------------------------------------------------------------------------*/
307void
308 softfloat_extF80MToCommonNaN(
309 const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
310
311/*----------------------------------------------------------------------------
312| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
313| floating-point NaN, and stores this NaN at the location pointed to by
314| 'zSPtr'.
315*----------------------------------------------------------------------------*/
316void
317 softfloat_commonNaNToExtF80M(
318 const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
319
320/*----------------------------------------------------------------------------
321| Assuming at least one of the two 80-bit extended floating-point values
322| pointed to by 'aSPtr' and 'bSPtr' is a NaN, stores the combined NaN result
323| at the location pointed to by 'zSPtr'. If either original floating-point
324| value is a signaling NaN, the invalid exception is raised.
325*----------------------------------------------------------------------------*/
326void
327 softfloat_propagateNaNExtF80M(
328 const struct extFloat80M *aSPtr,
329 const struct extFloat80M *bSPtr,
330 struct extFloat80M *zSPtr
331 );
332
333/*----------------------------------------------------------------------------
334| The bit pattern for a default generated 128-bit floating-point NaN.
335*----------------------------------------------------------------------------*/
336#define defaultNaNF128UI96 0xFFFF8000
337#define defaultNaNF128UI64 0
338#define defaultNaNF128UI32 0
339#define defaultNaNF128UI0 0
340
341/*----------------------------------------------------------------------------
342| Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN,
343| converts this NaN to the common NaN form, and stores the resulting common
344| NaN at the location pointed to by 'zPtr'. If the NaN is a signaling NaN,
345| the invalid exception is raised. Argument 'aWPtr' points to an array of
346| four 32-bit elements that concatenate in the platform's normal endian order
347| to form a 128-bit floating-point value.
348*----------------------------------------------------------------------------*/
349void
350 softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
351
352/*----------------------------------------------------------------------------
353| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
354| NaN, and stores this NaN at the location pointed to by 'zWPtr'. Argument
355| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
356| platform's normal endian order to form a 128-bit floating-point value.
357*----------------------------------------------------------------------------*/
358void
359 softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
360
361/*----------------------------------------------------------------------------
362| Assuming at least one of the two 128-bit floating-point values pointed to by
363| 'aWPtr' and 'bWPtr' is a NaN, stores the combined NaN result at the location
364| pointed to by 'zWPtr'. If either original floating-point value is a
365| signaling NaN, the invalid exception is raised. Each of 'aWPtr', 'bWPtr',
366| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
367| the platform's normal endian order to form a 128-bit floating-point value.
368*----------------------------------------------------------------------------*/
369void
370 softfloat_propagateNaNF128M(
371 const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
372
373#endif
374
375#endif
376
deps/SoftFloat-3e/source/8086/extF80M_isSignalingNaN.c deleted-57
...@@ -1,57 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43*----------------------------------------------------------------------------*/
44bool extF80M_isSignalingNaN( const extFloat80_t *aPtr )
45{
46 const struct extFloat80M *aSPtr;
47 uint64_t uiA0;
48
49 aSPtr = (const struct extFloat80M *) aPtr;
50 if ( (aSPtr->signExp & 0x7FFF) != 0x7FFF ) return false;
51 uiA0 = aSPtr->signif;
52 return
53 ! (uiA0 & UINT64_C( 0x4000000000000000 ))
54 && (uiA0 & UINT64_C( 0x3FFFFFFFFFFFFFFF));
55
56}
57
deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c deleted-60
...@@ -1,60 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "primitives.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44*----------------------------------------------------------------------------*/
45bool f128M_isSignalingNaN( const float128_t *aPtr )
46{
47 const uint32_t *aWPtr;
48 uint32_t uiA96;
49
50 aWPtr = (const uint32_t *) aPtr;
51 uiA96 = aWPtr[indexWordHi( 4 )];
52 if ( (uiA96 & 0x7FFF8000) != 0x7FFF0000 ) return false;
53 return
54 ((uiA96 & 0x00007FFF) != 0)
55 || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
56 | aWPtr[indexWord( 4, 0 )])
57 != 0);
58
59}
60
deps/SoftFloat-3e/source/8086/s_commonNaNToExtF80M.c deleted-56
...@@ -1,56 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "specialize.h"
41
42/*----------------------------------------------------------------------------
43| Converts the common NaN pointed to by `aPtr' into an 80-bit extended
44| floating-point NaN, and stores this NaN at the location pointed to by
45| `zSPtr'.
46*----------------------------------------------------------------------------*/
47void
48 softfloat_commonNaNToExtF80M(
49 const struct commonNaN *aPtr, struct extFloat80M *zSPtr )
50{
51
52 zSPtr->signExp = packToExtF80UI64( aPtr->sign, 0x7FFF );
53 zSPtr->signif = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1;
54
55}
56
deps/SoftFloat-3e/source/8086/s_commonNaNToExtF80UI.c deleted-56
...@@ -1,56 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41
42/*----------------------------------------------------------------------------
43| Converts the common NaN pointed to by `aPtr' into an 80-bit extended
44| floating-point NaN, and returns the bit pattern of this value as an unsigned
45| integer.
46*----------------------------------------------------------------------------*/
47struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr )
48{
49 struct uint128 uiZ;
50
51 uiZ.v64 = (uint_fast16_t) aPtr->sign<<15 | 0x7FFF;
52 uiZ.v0 = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1;
53 return uiZ;
54
55}
56
deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c deleted-56
...@@ -1,56 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41
42/*----------------------------------------------------------------------------
43| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point
44| NaN, and stores this NaN at the location pointed to by `zWPtr'. Argument
45| `zWPtr' points to an array of four 32-bit elements that concatenate in the
46| platform's normal endian order to form a 128-bit floating-point value.
47*----------------------------------------------------------------------------*/
48void
49 softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr )
50{
51
52 softfloat_shortShiftRight128M( (const uint32_t *) &aPtr->v0, 16, zWPtr );
53 zWPtr[indexWordHi( 4 )] |= (uint32_t) aPtr->sign<<31 | 0x7FFF8000;
54
55}
56
deps/SoftFloat-3e/source/8086/s_commonNaNToF128UI.c deleted-55
...@@ -1,55 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41
42/*----------------------------------------------------------------------------
43| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point
44| NaN, and returns the bit pattern of this value as an unsigned integer.
45*----------------------------------------------------------------------------*/
46struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
47{
48 struct uint128 uiZ;
49
50 uiZ = softfloat_shortShiftRight128( aPtr->v64, aPtr->v0, 16 );
51 uiZ.v64 |= (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FFF800000000000 );
52 return uiZ;
53
54}
55
deps/SoftFloat-3e/source/8086/s_commonNaNToF16UI.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40
41/*----------------------------------------------------------------------------
42| Converts the common NaN pointed to by `aPtr' into a 16-bit floating-point
43| NaN, and returns the bit pattern of this value as an unsigned integer.
44*----------------------------------------------------------------------------*/
45uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr )
46{
47
48 return (uint_fast16_t) aPtr->sign<<15 | 0x7E00 | aPtr->v64>>54;
49
50}
51
deps/SoftFloat-3e/source/8086/s_commonNaNToF32UI.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40
41/*----------------------------------------------------------------------------
42| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point
43| NaN, and returns the bit pattern of this value as an unsigned integer.
44*----------------------------------------------------------------------------*/
45uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr )
46{
47
48 return (uint_fast32_t) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41;
49
50}
51
deps/SoftFloat-3e/source/8086/s_commonNaNToF64UI.c deleted-53
...@@ -1,53 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40
41/*----------------------------------------------------------------------------
42| Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point
43| NaN, and returns the bit pattern of this value as an unsigned integer.
44*----------------------------------------------------------------------------*/
45uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr )
46{
47
48 return
49 (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FF8000000000000 )
50 | aPtr->v64>>12;
51
52}
53
deps/SoftFloat-3e/source/8086/s_extF80MToCommonNaN.c deleted-62
...@@ -1,62 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44| Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is
45| a NaN, converts this NaN to the common NaN form, and stores the resulting
46| common NaN at the location pointed to by `zPtr'. If the NaN is a signaling
47| NaN, the invalid exception is raised.
48*----------------------------------------------------------------------------*/
49void
50 softfloat_extF80MToCommonNaN(
51 const struct extFloat80M *aSPtr, struct commonNaN *zPtr )
52{
53
54 if ( extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ) ) {
55 softfloat_raiseFlags( softfloat_flag_invalid );
56 }
57 zPtr->sign = signExtF80UI64( aSPtr->signExp );
58 zPtr->v64 = aSPtr->signif<<1;
59 zPtr->v0 = 0;
60
61}
62
deps/SoftFloat-3e/source/8086/s_extF80UIToCommonNaN.c deleted-62
...@@ -1,62 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0'
44| has the bit pattern of an 80-bit extended floating-point NaN, converts
45| this NaN to the common NaN form, and stores the resulting common NaN at the
46| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
47| exception is raised.
48*----------------------------------------------------------------------------*/
49void
50 softfloat_extF80UIToCommonNaN(
51 uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr )
52{
53
54 if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ) {
55 softfloat_raiseFlags( softfloat_flag_invalid );
56 }
57 zPtr->sign = uiA64>>15;
58 zPtr->v64 = uiA0<<1;
59 zPtr->v0 = 0;
60
61}
62
deps/SoftFloat-3e/source/8086/s_f128MToCommonNaN.c deleted-62
...@@ -1,62 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44| Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN,
45| converts this NaN to the common NaN form, and stores the resulting common
46| NaN at the location pointed to by `zPtr'. If the NaN is a signaling NaN,
47| the invalid exception is raised. Argument `aWPtr' points to an array of
48| four 32-bit elements that concatenate in the platform's normal endian order
49| to form a 128-bit floating-point value.
50*----------------------------------------------------------------------------*/
51void
52 softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr )
53{
54
55 if ( f128M_isSignalingNaN( (const float128_t *) aWPtr ) ) {
56 softfloat_raiseFlags( softfloat_flag_invalid );
57 }
58 zPtr->sign = aWPtr[indexWordHi( 4 )]>>31;
59 softfloat_shortShiftLeft128M( aWPtr, 16, (uint32_t *) &zPtr->v0 );
60
61}
62
deps/SoftFloat-3e/source/8086/s_f128UIToCommonNaN.c deleted-65
...@@ -1,65 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0'
45| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to
46| the common NaN form, and stores the resulting common NaN at the location
47| pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception
48| is raised.
49*----------------------------------------------------------------------------*/
50void
51 softfloat_f128UIToCommonNaN(
52 uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr )
53{
54 struct uint128 NaNSig;
55
56 if ( softfloat_isSigNaNF128UI( uiA64, uiA0 ) ) {
57 softfloat_raiseFlags( softfloat_flag_invalid );
58 }
59 NaNSig = softfloat_shortShiftLeft128( uiA64, uiA0, 16 );
60 zPtr->sign = uiA64>>63;
61 zPtr->v64 = NaNSig.v64;
62 zPtr->v0 = NaNSig.v0;
63
64}
65
deps/SoftFloat-3e/source/8086/s_f16UIToCommonNaN.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Assuming `uiA' has the bit pattern of a 16-bit floating-point NaN, converts
44| this NaN to the common NaN form, and stores the resulting common NaN at the
45| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
46| exception is raised.
47*----------------------------------------------------------------------------*/
48void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr )
49{
50
51 if ( softfloat_isSigNaNF16UI( uiA ) ) {
52 softfloat_raiseFlags( softfloat_flag_invalid );
53 }
54 zPtr->sign = uiA>>15;
55 zPtr->v64 = (uint_fast64_t) uiA<<54;
56 zPtr->v0 = 0;
57
58}
59
deps/SoftFloat-3e/source/8086/s_f32UIToCommonNaN.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts
44| this NaN to the common NaN form, and stores the resulting common NaN at the
45| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
46| exception is raised.
47*----------------------------------------------------------------------------*/
48void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr )
49{
50
51 if ( softfloat_isSigNaNF32UI( uiA ) ) {
52 softfloat_raiseFlags( softfloat_flag_invalid );
53 }
54 zPtr->sign = uiA>>31;
55 zPtr->v64 = (uint_fast64_t) uiA<<41;
56 zPtr->v0 = 0;
57
58}
59
deps/SoftFloat-3e/source/8086/s_f64UIToCommonNaN.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts
44| this NaN to the common NaN form, and stores the resulting common NaN at the
45| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
46| exception is raised.
47*----------------------------------------------------------------------------*/
48void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr )
49{
50
51 if ( softfloat_isSigNaNF64UI( uiA ) ) {
52 softfloat_raiseFlags( softfloat_flag_invalid );
53 }
54 zPtr->sign = uiA>>63;
55 zPtr->v64 = uiA<<12;
56 zPtr->v0 = 0;
57
58}
59
deps/SoftFloat-3e/source/8086/s_propagateNaNExtF80M.c deleted-107
...@@ -1,107 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Assuming at least one of the two 80-bit extended floating-point values
46| pointed to by `aSPtr' and `bSPtr' is a NaN, stores the combined NaN result
47| at the location pointed to by `zSPtr'. If either original floating-point
48| value is a signaling NaN, the invalid exception is raised.
49*----------------------------------------------------------------------------*/
50void
51 softfloat_propagateNaNExtF80M(
52 const struct extFloat80M *aSPtr,
53 const struct extFloat80M *bSPtr,
54 struct extFloat80M *zSPtr
55 )
56{
57 bool isSigNaNA;
58 const struct extFloat80M *sPtr;
59 bool isSigNaNB;
60 uint_fast16_t uiB64;
61 uint64_t uiB0;
62 uint_fast16_t uiA64;
63 uint64_t uiA0;
64 uint_fast16_t uiMagA64, uiMagB64;
65
66 isSigNaNA = extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr );
67 sPtr = aSPtr;
68 if ( ! bSPtr ) {
69 if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid );
70 goto copy;
71 }
72 isSigNaNB = extF80M_isSignalingNaN( (const extFloat80_t *) bSPtr );
73 if ( isSigNaNA | isSigNaNB ) {
74 softfloat_raiseFlags( softfloat_flag_invalid );
75 if ( isSigNaNA ) {
76 uiB64 = bSPtr->signExp;
77 if ( isSigNaNB ) goto returnLargerUIMag;
78 uiB0 = bSPtr->signif;
79 if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto copyB;
80 goto copy;
81 } else {
82 uiA64 = aSPtr->signExp;
83 uiA0 = aSPtr->signif;
84 if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto copy;
85 goto copyB;
86 }
87 }
88 uiB64 = bSPtr->signExp;
89 returnLargerUIMag:
90 uiA64 = aSPtr->signExp;
91 uiMagA64 = uiA64 & 0x7FFF;
92 uiMagB64 = uiB64 & 0x7FFF;
93 if ( uiMagA64 < uiMagB64 ) goto copyB;
94 if ( uiMagB64 < uiMagA64 ) goto copy;
95 uiA0 = aSPtr->signif;
96 uiB0 = bSPtr->signif;
97 if ( uiA0 < uiB0 ) goto copyB;
98 if ( uiB0 < uiA0 ) goto copy;
99 if ( uiA64 < uiB64 ) goto copy;
100 copyB:
101 sPtr = bSPtr;
102 copy:
103 zSPtr->signExp = sPtr->signExp;
104 zSPtr->signif = sPtr->signif | UINT64_C( 0xC000000000000000 );
105
106}
107
deps/SoftFloat-3e/source/8086/s_propagateNaNExtF80UI.c deleted-106
...@@ -1,106 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2018 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting the unsigned integer formed from concatenating 'uiA64' and
46| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting
47| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
48| 80-bit extended floating-point value, and assuming at least on of these
49| floating-point values is a NaN, returns the bit pattern of the combined NaN
50| result. If either original floating-point value is a signaling NaN, the
51| invalid exception is raised.
52*----------------------------------------------------------------------------*/
53struct uint128
54 softfloat_propagateNaNExtF80UI(
55 uint_fast16_t uiA64,
56 uint_fast64_t uiA0,
57 uint_fast16_t uiB64,
58 uint_fast64_t uiB0
59 )
60{
61 bool isSigNaNA, isSigNaNB;
62 uint_fast64_t uiNonsigA0, uiNonsigB0;
63 uint_fast16_t uiMagA64, uiMagB64;
64 struct uint128 uiZ;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 isSigNaNA = softfloat_isSigNaNExtF80UI( uiA64, uiA0 );
69 isSigNaNB = softfloat_isSigNaNExtF80UI( uiB64, uiB0 );
70 /*------------------------------------------------------------------------
71 | Make NaNs non-signaling.
72 *------------------------------------------------------------------------*/
73 uiNonsigA0 = uiA0 | UINT64_C( 0xC000000000000000 );
74 uiNonsigB0 = uiB0 | UINT64_C( 0xC000000000000000 );
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 if ( isSigNaNA | isSigNaNB ) {
78 softfloat_raiseFlags( softfloat_flag_invalid );
79 if ( isSigNaNA ) {
80 if ( isSigNaNB ) goto returnLargerMag;
81 if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto returnB;
82 goto returnA;
83 } else {
84 if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto returnA;
85 goto returnB;
86 }
87 }
88 returnLargerMag:
89 uiMagA64 = uiA64 & 0x7FFF;
90 uiMagB64 = uiB64 & 0x7FFF;
91 if ( uiMagA64 < uiMagB64 ) goto returnB;
92 if ( uiMagB64 < uiMagA64 ) goto returnA;
93 if ( uiA0 < uiB0 ) goto returnB;
94 if ( uiB0 < uiA0 ) goto returnA;
95 if ( uiA64 < uiB64 ) goto returnA;
96 returnB:
97 uiZ.v64 = uiB64;
98 uiZ.v0 = uiNonsigB0;
99 return uiZ;
100 returnA:
101 uiZ.v64 = uiA64;
102 uiZ.v0 = uiNonsigA0;
103 return uiZ;
104
105}
106
deps/SoftFloat-3e/source/8086/s_propagateNaNF128M.c deleted-108
...@@ -1,108 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Assuming at least one of the two 128-bit floating-point values pointed to by
46| `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location
47| pointed to by `zWPtr'. If either original floating-point value is a
48| signaling NaN, the invalid exception is raised. Each of `aWPtr', `bWPtr',
49| and `zWPtr' points to an array of four 32-bit elements that concatenate in
50| the platform's normal endian order to form a 128-bit floating-point value.
51*----------------------------------------------------------------------------*/
52void
53 softfloat_propagateNaNF128M(
54 const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr )
55{
56 bool isSigNaNA;
57 const uint32_t *ptr;
58 bool isSigNaNB;
59 uint32_t uiA96, uiB96, wordMagA, wordMagB;
60
61 isSigNaNA = f128M_isSignalingNaN( (const float128_t *) aWPtr );
62 ptr = aWPtr;
63 if ( ! bWPtr ) {
64 if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid );
65 goto copy;
66 }
67 isSigNaNB = f128M_isSignalingNaN( (const float128_t *) bWPtr );
68 if ( isSigNaNA | isSigNaNB ) {
69 softfloat_raiseFlags( softfloat_flag_invalid );
70 if ( isSigNaNA ) {
71 if ( isSigNaNB ) goto returnLargerUIMag;
72 if ( softfloat_isNaNF128M( bWPtr ) ) goto copyB;
73 goto copy;
74 } else {
75 if ( softfloat_isNaNF128M( aWPtr ) ) goto copy;
76 goto copyB;
77 }
78 }
79 returnLargerUIMag:
80 uiA96 = aWPtr[indexWordHi( 4 )];
81 uiB96 = bWPtr[indexWordHi( 4 )];
82 wordMagA = uiA96 & 0x7FFFFFFF;
83 wordMagB = uiB96 & 0x7FFFFFFF;
84 if ( wordMagA < wordMagB ) goto copyB;
85 if ( wordMagB < wordMagA ) goto copy;
86 wordMagA = aWPtr[indexWord( 4, 2 )];
87 wordMagB = bWPtr[indexWord( 4, 2 )];
88 if ( wordMagA < wordMagB ) goto copyB;
89 if ( wordMagB < wordMagA ) goto copy;
90 wordMagA = aWPtr[indexWord( 4, 1 )];
91 wordMagB = bWPtr[indexWord( 4, 1 )];
92 if ( wordMagA < wordMagB ) goto copyB;
93 if ( wordMagB < wordMagA ) goto copy;
94 wordMagA = aWPtr[indexWord( 4, 0 )];
95 wordMagB = bWPtr[indexWord( 4, 0 )];
96 if ( wordMagA < wordMagB ) goto copyB;
97 if ( wordMagB < wordMagA ) goto copy;
98 if ( uiA96 < uiB96 ) goto copy;
99 copyB:
100 ptr = bWPtr;
101 copy:
102 zWPtr[indexWordHi( 4 )] = ptr[indexWordHi( 4 )] | 0x00008000;
103 zWPtr[indexWord( 4, 2 )] = ptr[indexWord( 4, 2 )];
104 zWPtr[indexWord( 4, 1 )] = ptr[indexWord( 4, 1 )];
105 zWPtr[indexWord( 4, 0 )] = ptr[indexWord( 4, 0 )];
106
107}
108
deps/SoftFloat-3e/source/8086/s_propagateNaNF128UI.c deleted-105
...@@ -1,105 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2018 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting the unsigned integer formed from concatenating 'uiA64' and
46| 'uiA0' as a 128-bit floating-point value, and likewise interpreting the
47| unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
48| 128-bit floating-point value, and assuming at least on of these floating-
49| point values is a NaN, returns the bit pattern of the combined NaN result.
50| If either original floating-point value is a signaling NaN, the invalid
51| exception is raised.
52*----------------------------------------------------------------------------*/
53struct uint128
54 softfloat_propagateNaNF128UI(
55 uint_fast64_t uiA64,
56 uint_fast64_t uiA0,
57 uint_fast64_t uiB64,
58 uint_fast64_t uiB0
59 )
60{
61 bool isSigNaNA, isSigNaNB;
62 uint_fast64_t uiNonsigA64, uiNonsigB64, uiMagA64, uiMagB64;
63 struct uint128 uiZ;
64
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 );
68 isSigNaNB = softfloat_isSigNaNF128UI( uiB64, uiB0 );
69 /*------------------------------------------------------------------------
70 | Make NaNs non-signaling.
71 *------------------------------------------------------------------------*/
72 uiNonsigA64 = uiA64 | UINT64_C( 0x0000800000000000 );
73 uiNonsigB64 = uiB64 | UINT64_C( 0x0000800000000000 );
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( isSigNaNA | isSigNaNB ) {
77 softfloat_raiseFlags( softfloat_flag_invalid );
78 if ( isSigNaNA ) {
79 if ( isSigNaNB ) goto returnLargerMag;
80 if ( isNaNF128UI( uiB64, uiB0 ) ) goto returnB;
81 goto returnA;
82 } else {
83 if ( isNaNF128UI( uiA64, uiA0 ) ) goto returnA;
84 goto returnB;
85 }
86 }
87 returnLargerMag:
88 uiMagA64 = uiA64 & UINT64_C( 0x7FFFFFFFFFFFFFFF );
89 uiMagB64 = uiB64 & UINT64_C( 0x7FFFFFFFFFFFFFFF );
90 if ( uiMagA64 < uiMagB64 ) goto returnB;
91 if ( uiMagB64 < uiMagA64 ) goto returnA;
92 if ( uiA0 < uiB0 ) goto returnB;
93 if ( uiB0 < uiA0 ) goto returnA;
94 if ( uiNonsigA64 < uiNonsigB64 ) goto returnA;
95 returnB:
96 uiZ.v64 = uiNonsigB64;
97 uiZ.v0 = uiB0;
98 return uiZ;
99 returnA:
100 uiZ.v64 = uiNonsigA64;
101 uiZ.v0 = uiA0;
102 return uiZ;
103
104}
105
deps/SoftFloat-3e/source/8086/s_propagateNaNF16UI.c deleted-84
...@@ -1,84 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2018 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
46| point values, at least one of which is a NaN, returns the bit pattern of
47| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
48| signaling NaN, the invalid exception is raised.
49*----------------------------------------------------------------------------*/
50uint_fast16_t
51 softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB )
52{
53 bool isSigNaNA, isSigNaNB;
54 uint_fast16_t uiNonsigA, uiNonsigB, uiMagA, uiMagB;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 isSigNaNA = softfloat_isSigNaNF16UI( uiA );
59 isSigNaNB = softfloat_isSigNaNF16UI( uiB );
60 /*------------------------------------------------------------------------
61 | Make NaNs non-signaling.
62 *------------------------------------------------------------------------*/
63 uiNonsigA = uiA | 0x0200;
64 uiNonsigB = uiB | 0x0200;
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 if ( isSigNaNA | isSigNaNB ) {
68 softfloat_raiseFlags( softfloat_flag_invalid );
69 if ( isSigNaNA ) {
70 if ( isSigNaNB ) goto returnLargerMag;
71 return isNaNF16UI( uiB ) ? uiNonsigB : uiNonsigA;
72 } else {
73 return isNaNF16UI( uiA ) ? uiNonsigA : uiNonsigB;
74 }
75 }
76 returnLargerMag:
77 uiMagA = uiA & 0x7FFF;
78 uiMagB = uiB & 0x7FFF;
79 if ( uiMagA < uiMagB ) return uiNonsigB;
80 if ( uiMagB < uiMagA ) return uiNonsigA;
81 return (uiNonsigA < uiNonsigB) ? uiNonsigA : uiNonsigB;
82
83}
84
deps/SoftFloat-3e/source/8086/s_propagateNaNF32UI.c deleted-84
...@@ -1,84 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2018 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
46| point values, at least one of which is a NaN, returns the bit pattern of
47| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
48| signaling NaN, the invalid exception is raised.
49*----------------------------------------------------------------------------*/
50uint_fast32_t
51 softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB )
52{
53 bool isSigNaNA, isSigNaNB;
54 uint_fast32_t uiNonsigA, uiNonsigB, uiMagA, uiMagB;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 isSigNaNA = softfloat_isSigNaNF32UI( uiA );
59 isSigNaNB = softfloat_isSigNaNF32UI( uiB );
60 /*------------------------------------------------------------------------
61 | Make NaNs non-signaling.
62 *------------------------------------------------------------------------*/
63 uiNonsigA = uiA | 0x00400000;
64 uiNonsigB = uiB | 0x00400000;
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 if ( isSigNaNA | isSigNaNB ) {
68 softfloat_raiseFlags( softfloat_flag_invalid );
69 if ( isSigNaNA ) {
70 if ( isSigNaNB ) goto returnLargerMag;
71 return isNaNF32UI( uiB ) ? uiNonsigB : uiNonsigA;
72 } else {
73 return isNaNF32UI( uiA ) ? uiNonsigA : uiNonsigB;
74 }
75 }
76 returnLargerMag:
77 uiMagA = uiA & 0x7FFFFFFF;
78 uiMagB = uiB & 0x7FFFFFFF;
79 if ( uiMagA < uiMagB ) return uiNonsigB;
80 if ( uiMagB < uiMagA ) return uiNonsigA;
81 return (uiNonsigA < uiNonsigB) ? uiNonsigA : uiNonsigB;
82
83}
84
deps/SoftFloat-3e/source/8086/s_propagateNaNF64UI.c deleted-84
...@@ -1,84 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2018 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
46| point values, at least one of which is a NaN, returns the bit pattern of
47| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
48| signaling NaN, the invalid exception is raised.
49*----------------------------------------------------------------------------*/
50uint_fast64_t
51 softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB )
52{
53 bool isSigNaNA, isSigNaNB;
54 uint_fast64_t uiNonsigA, uiNonsigB, uiMagA, uiMagB;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 isSigNaNA = softfloat_isSigNaNF64UI( uiA );
59 isSigNaNB = softfloat_isSigNaNF64UI( uiB );
60 /*------------------------------------------------------------------------
61 | Make NaNs non-signaling.
62 *------------------------------------------------------------------------*/
63 uiNonsigA = uiA | UINT64_C( 0x0008000000000000 );
64 uiNonsigB = uiB | UINT64_C( 0x0008000000000000 );
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 if ( isSigNaNA | isSigNaNB ) {
68 softfloat_raiseFlags( softfloat_flag_invalid );
69 if ( isSigNaNA ) {
70 if ( isSigNaNB ) goto returnLargerMag;
71 return isNaNF64UI( uiB ) ? uiNonsigB : uiNonsigA;
72 } else {
73 return isNaNF64UI( uiA ) ? uiNonsigA : uiNonsigB;
74 }
75 }
76 returnLargerMag:
77 uiMagA = uiA & UINT64_C( 0x7FFFFFFFFFFFFFFF );
78 uiMagB = uiB & UINT64_C( 0x7FFFFFFFFFFFFFFF );
79 if ( uiMagA < uiMagB ) return uiNonsigB;
80 if ( uiMagB < uiMagA ) return uiNonsigA;
81 return (uiNonsigA < uiNonsigB) ? uiNonsigA : uiNonsigB;
82
83}
84
deps/SoftFloat-3e/source/8086/softfloat_raiseFlags.c deleted-52
...@@ -1,52 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include "platform.h"
38#include "softfloat.h"
39
40/*----------------------------------------------------------------------------
41| Raises the exceptions specified by `flags'. Floating-point traps can be
42| defined here if desired. It is currently not possible for such a trap
43| to substitute a result value. If traps are not implemented, this routine
44| should be simply `softfloat_exceptionFlags |= flags;'.
45*----------------------------------------------------------------------------*/
46void softfloat_raiseFlags( uint_fast8_t flags )
47{
48
49 softfloat_exceptionFlags |= flags;
50
51}
52
deps/SoftFloat-3e/source/8086/specialize.h deleted-376
...@@ -1,376 +0,0 @@
1
2/*============================================================================
3
4This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2018 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#ifndef specialize_h
38#define specialize_h 1
39
40#include <stdbool.h>
41#include <stdint.h>
42#include "primitiveTypes.h"
43#include "softfloat.h"
44
45/*----------------------------------------------------------------------------
46| Default value for 'softfloat_detectTininess'.
47*----------------------------------------------------------------------------*/
48#define init_detectTininess softfloat_tininess_afterRounding
49
50/*----------------------------------------------------------------------------
51| The values to return on conversions to 32-bit integer formats that raise an
52| invalid exception.
53*----------------------------------------------------------------------------*/
54#define ui32_fromPosOverflow 0xFFFFFFFF
55#define ui32_fromNegOverflow 0xFFFFFFFF
56#define ui32_fromNaN 0xFFFFFFFF
57#define i32_fromPosOverflow (-0x7FFFFFFF - 1)
58#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
59#define i32_fromNaN (-0x7FFFFFFF - 1)
60
61/*----------------------------------------------------------------------------
62| The values to return on conversions to 64-bit integer formats that raise an
63| invalid exception.
64*----------------------------------------------------------------------------*/
65#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
66#define ui64_fromNegOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
67#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF )
68#define i64_fromPosOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
69#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
70#define i64_fromNaN (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
71
72/*----------------------------------------------------------------------------
73| "Common NaN" structure, used to transfer NaN representations from one format
74| to another.
75*----------------------------------------------------------------------------*/
76struct commonNaN {
77 bool sign;
78#ifdef LITTLEENDIAN
79 uint64_t v0, v64;
80#else
81 uint64_t v64, v0;
82#endif
83};
84
85/*----------------------------------------------------------------------------
86| The bit pattern for a default generated 16-bit floating-point NaN.
87*----------------------------------------------------------------------------*/
88#define defaultNaNF16UI 0xFE00
89
90/*----------------------------------------------------------------------------
91| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a
92| 16-bit floating-point signaling NaN.
93| Note: This macro evaluates its argument more than once.
94*----------------------------------------------------------------------------*/
95#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF))
96
97/*----------------------------------------------------------------------------
98| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts
99| this NaN to the common NaN form, and stores the resulting common NaN at the
100| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
101| exception is raised.
102*----------------------------------------------------------------------------*/
103void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr );
104
105/*----------------------------------------------------------------------------
106| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
107| NaN, and returns the bit pattern of this value as an unsigned integer.
108*----------------------------------------------------------------------------*/
109uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
110
111/*----------------------------------------------------------------------------
112| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
113| point values, at least one of which is a NaN, returns the bit pattern of
114| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
115| signaling NaN, the invalid exception is raised.
116*----------------------------------------------------------------------------*/
117uint_fast16_t
118 softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
119
120/*----------------------------------------------------------------------------
121| The bit pattern for a default generated 32-bit floating-point NaN.
122*----------------------------------------------------------------------------*/
123#define defaultNaNF32UI 0xFFC00000
124
125/*----------------------------------------------------------------------------
126| Returns true when 32-bit unsigned integer 'uiA' has the bit pattern of a
127| 32-bit floating-point signaling NaN.
128| Note: This macro evaluates its argument more than once.
129*----------------------------------------------------------------------------*/
130#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF))
131
132/*----------------------------------------------------------------------------
133| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts
134| this NaN to the common NaN form, and stores the resulting common NaN at the
135| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
136| exception is raised.
137*----------------------------------------------------------------------------*/
138void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr );
139
140/*----------------------------------------------------------------------------
141| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point
142| NaN, and returns the bit pattern of this value as an unsigned integer.
143*----------------------------------------------------------------------------*/
144uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
145
146/*----------------------------------------------------------------------------
147| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
148| point values, at least one of which is a NaN, returns the bit pattern of
149| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
150| signaling NaN, the invalid exception is raised.
151*----------------------------------------------------------------------------*/
152uint_fast32_t
153 softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
154
155/*----------------------------------------------------------------------------
156| The bit pattern for a default generated 64-bit floating-point NaN.
157*----------------------------------------------------------------------------*/
158#define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 )
159
160/*----------------------------------------------------------------------------
161| Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a
162| 64-bit floating-point signaling NaN.
163| Note: This macro evaluates its argument more than once.
164*----------------------------------------------------------------------------*/
165#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF )))
166
167/*----------------------------------------------------------------------------
168| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
169| this NaN to the common NaN form, and stores the resulting common NaN at the
170| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
171| exception is raised.
172*----------------------------------------------------------------------------*/
173void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr );
174
175/*----------------------------------------------------------------------------
176| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point
177| NaN, and returns the bit pattern of this value as an unsigned integer.
178*----------------------------------------------------------------------------*/
179uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
180
181/*----------------------------------------------------------------------------
182| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
183| point values, at least one of which is a NaN, returns the bit pattern of
184| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
185| signaling NaN, the invalid exception is raised.
186*----------------------------------------------------------------------------*/
187uint_fast64_t
188 softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
189
190/*----------------------------------------------------------------------------
191| The bit pattern for a default generated 80-bit extended floating-point NaN.
192*----------------------------------------------------------------------------*/
193#define defaultNaNExtF80UI64 0xFFFF
194#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 )
195
196/*----------------------------------------------------------------------------
197| Returns true when the 80-bit unsigned integer formed from concatenating
198| 16-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of an 80-bit extended
199| floating-point signaling NaN.
200| Note: This macro evaluates its arguments more than once.
201*----------------------------------------------------------------------------*/
202#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
203
204#ifdef SOFTFLOAT_FAST_INT64
205
206/*----------------------------------------------------------------------------
207| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is
208| defined.
209*----------------------------------------------------------------------------*/
210
211/*----------------------------------------------------------------------------
212| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
213| has the bit pattern of an 80-bit extended floating-point NaN, converts
214| this NaN to the common NaN form, and stores the resulting common NaN at the
215| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
216| exception is raised.
217*----------------------------------------------------------------------------*/
218void
219 softfloat_extF80UIToCommonNaN(
220 uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
221
222/*----------------------------------------------------------------------------
223| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
224| floating-point NaN, and returns the bit pattern of this value as an unsigned
225| integer.
226*----------------------------------------------------------------------------*/
227struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
228
229/*----------------------------------------------------------------------------
230| Interpreting the unsigned integer formed from concatenating 'uiA64' and
231| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting
232| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
233| 80-bit extended floating-point value, and assuming at least on of these
234| floating-point values is a NaN, returns the bit pattern of the combined NaN
235| result. If either original floating-point value is a signaling NaN, the
236| invalid exception is raised.
237*----------------------------------------------------------------------------*/
238struct uint128
239 softfloat_propagateNaNExtF80UI(
240 uint_fast16_t uiA64,
241 uint_fast64_t uiA0,
242 uint_fast16_t uiB64,
243 uint_fast64_t uiB0
244 );
245
246/*----------------------------------------------------------------------------
247| The bit pattern for a default generated 128-bit floating-point NaN.
248*----------------------------------------------------------------------------*/
249#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 )
250#define defaultNaNF128UI0 UINT64_C( 0 )
251
252/*----------------------------------------------------------------------------
253| Returns true when the 128-bit unsigned integer formed from concatenating
254| 64-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of a 128-bit floating-
255| point signaling NaN.
256| Note: This macro evaluates its arguments more than once.
257*----------------------------------------------------------------------------*/
258#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
259
260/*----------------------------------------------------------------------------
261| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
262| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to
263| the common NaN form, and stores the resulting common NaN at the location
264| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
265| is raised.
266*----------------------------------------------------------------------------*/
267void
268 softfloat_f128UIToCommonNaN(
269 uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
270
271/*----------------------------------------------------------------------------
272| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
273| NaN, and returns the bit pattern of this value as an unsigned integer.
274*----------------------------------------------------------------------------*/
275struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
276
277/*----------------------------------------------------------------------------
278| Interpreting the unsigned integer formed from concatenating 'uiA64' and
279| 'uiA0' as a 128-bit floating-point value, and likewise interpreting the
280| unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
281| 128-bit floating-point value, and assuming at least on of these floating-
282| point values is a NaN, returns the bit pattern of the combined NaN result.
283| If either original floating-point value is a signaling NaN, the invalid
284| exception is raised.
285*----------------------------------------------------------------------------*/
286struct uint128
287 softfloat_propagateNaNF128UI(
288 uint_fast64_t uiA64,
289 uint_fast64_t uiA0,
290 uint_fast64_t uiB64,
291 uint_fast64_t uiB0
292 );
293
294#else
295
296/*----------------------------------------------------------------------------
297| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is not
298| defined.
299*----------------------------------------------------------------------------*/
300
301/*----------------------------------------------------------------------------
302| Assuming the 80-bit extended floating-point value pointed to by 'aSPtr' is
303| a NaN, converts this NaN to the common NaN form, and stores the resulting
304| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
305| NaN, the invalid exception is raised.
306*----------------------------------------------------------------------------*/
307void
308 softfloat_extF80MToCommonNaN(
309 const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
310
311/*----------------------------------------------------------------------------
312| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
313| floating-point NaN, and stores this NaN at the location pointed to by
314| 'zSPtr'.
315*----------------------------------------------------------------------------*/
316void
317 softfloat_commonNaNToExtF80M(
318 const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
319
320/*----------------------------------------------------------------------------
321| Assuming at least one of the two 80-bit extended floating-point values
322| pointed to by 'aSPtr' and 'bSPtr' is a NaN, stores the combined NaN result
323| at the location pointed to by 'zSPtr'. If either original floating-point
324| value is a signaling NaN, the invalid exception is raised.
325*----------------------------------------------------------------------------*/
326void
327 softfloat_propagateNaNExtF80M(
328 const struct extFloat80M *aSPtr,
329 const struct extFloat80M *bSPtr,
330 struct extFloat80M *zSPtr
331 );
332
333/*----------------------------------------------------------------------------
334| The bit pattern for a default generated 128-bit floating-point NaN.
335*----------------------------------------------------------------------------*/
336#define defaultNaNF128UI96 0xFFFF8000
337#define defaultNaNF128UI64 0
338#define defaultNaNF128UI32 0
339#define defaultNaNF128UI0 0
340
341/*----------------------------------------------------------------------------
342| Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN,
343| converts this NaN to the common NaN form, and stores the resulting common
344| NaN at the location pointed to by 'zPtr'. If the NaN is a signaling NaN,
345| the invalid exception is raised. Argument 'aWPtr' points to an array of
346| four 32-bit elements that concatenate in the platform's normal endian order
347| to form a 128-bit floating-point value.
348*----------------------------------------------------------------------------*/
349void
350 softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
351
352/*----------------------------------------------------------------------------
353| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
354| NaN, and stores this NaN at the location pointed to by 'zWPtr'. Argument
355| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
356| platform's normal endian order to form a 128-bit floating-point value.
357*----------------------------------------------------------------------------*/
358void
359 softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
360
361/*----------------------------------------------------------------------------
362| Assuming at least one of the two 128-bit floating-point values pointed to by
363| 'aWPtr' and 'bWPtr' is a NaN, stores the combined NaN result at the location
364| pointed to by 'zWPtr'. If either original floating-point value is a
365| signaling NaN, the invalid exception is raised. Each of 'aWPtr', 'bWPtr',
366| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
367| the platform's normal endian order to form a 128-bit floating-point value.
368*----------------------------------------------------------------------------*/
369void
370 softfloat_propagateNaNF128M(
371 const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
372
373#endif
374
375#endif
376
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/extF80M_isSignalingNaN.c deleted-57
...@@ -1,57 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43*----------------------------------------------------------------------------*/
44bool extF80M_isSignalingNaN( const extFloat80_t *aPtr )
45{
46 const struct extFloat80M *aSPtr;
47 uint64_t uiA0;
48
49 aSPtr = (const struct extFloat80M *) aPtr;
50 if ( (aSPtr->signExp & 0x7FFF) != 0x7FFF ) return false;
51 uiA0 = aSPtr->signif;
52 return
53 ! (uiA0 & UINT64_C( 0x4000000000000000 ))
54 && (uiA0 & UINT64_C( 0x3FFFFFFFFFFFFFFF));
55
56}
57
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/f128M_isSignalingNaN.c deleted-60
...@@ -1,60 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "primitives.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44*----------------------------------------------------------------------------*/
45bool f128M_isSignalingNaN( const float128_t *aPtr )
46{
47 const uint32_t *aWPtr;
48 uint32_t uiA96;
49
50 aWPtr = (const uint32_t *) aPtr;
51 uiA96 = aWPtr[indexWordHi( 4 )];
52 if ( (uiA96 & 0x7FFF8000) != 0x7FFF0000 ) return false;
53 return
54 ((uiA96 & 0x00007FFF) != 0)
55 || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
56 | aWPtr[indexWord( 4, 0 )])
57 != 0);
58
59}
60
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_commonNaNToExtF80M.c deleted-57
...@@ -1,57 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include "platform.h"
38#include "softfloat_types.h"
39
40#define softfloat_commonNaNToExtF80M softfloat_commonNaNToExtF80M
41#include "specialize.h"
42
43/*----------------------------------------------------------------------------
44| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
45| floating-point NaN, and stores this NaN at the location pointed to by
46| 'zSPtr'.
47*----------------------------------------------------------------------------*/
48void
49 softfloat_commonNaNToExtF80M(
50 const struct commonNaN *aPtr, struct extFloat80M *zSPtr )
51{
52
53 zSPtr->signExp = defaultNaNExtF80UI64;
54 zSPtr->signif = defaultNaNExtF80UI0;
55
56}
57
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_commonNaNToExtF80UI.c deleted-57
...@@ -1,57 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include "platform.h"
38#include "primitiveTypes.h"
39
40#define softfloat_commonNaNToExtF80UI softfloat_commonNaNToExtF80UI
41#include "specialize.h"
42
43/*----------------------------------------------------------------------------
44| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
45| floating-point NaN, and returns the bit pattern of this value as an unsigned
46| integer.
47*----------------------------------------------------------------------------*/
48struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr )
49{
50 struct uint128 uiZ;
51
52 uiZ.v64 = defaultNaNExtF80UI64;
53 uiZ.v0 = defaultNaNExtF80UI0;
54 return uiZ;
55
56}
57
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_commonNaNToF128M.c deleted-60
...@@ -1,60 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#define softfloat_commonNaNToF128M softfloat_commonNaNToF128M
42#include "specialize.h"
43
44/*----------------------------------------------------------------------------
45| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
46| NaN, and stores this NaN at the location pointed to by 'zWPtr'. Argument
47| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
48| platform's normal endian order to form a 128-bit floating-point value.
49*----------------------------------------------------------------------------*/
50void
51 softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr )
52{
53
54 zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96;
55 zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64;
56 zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32;
57 zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0;
58
59}
60
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_commonNaNToF128UI.c deleted-56
...@@ -1,56 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include "platform.h"
38#include "primitiveTypes.h"
39
40#define softfloat_commonNaNToF128UI softfloat_commonNaNToF128UI
41#include "specialize.h"
42
43/*----------------------------------------------------------------------------
44| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
45| NaN, and returns the bit pattern of this value as an unsigned integer.
46*----------------------------------------------------------------------------*/
47struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
48{
49 struct uint128 uiZ;
50
51 uiZ.v64 = defaultNaNF128UI64;
52 uiZ.v0 = defaultNaNF128UI0;
53 return uiZ;
54
55}
56
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_commonNaNToF16UI.c deleted-5
...@@ -1,5 +0,0 @@
1
2/*----------------------------------------------------------------------------
3| This file intentionally contains no code.
4*----------------------------------------------------------------------------*/
5
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_commonNaNToF32UI.c deleted-5
...@@ -1,5 +0,0 @@
1
2/*----------------------------------------------------------------------------
3| This file intentionally contains no code.
4*----------------------------------------------------------------------------*/
5
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_commonNaNToF64UI.c deleted-5
...@@ -1,5 +0,0 @@
1
2/*----------------------------------------------------------------------------
3| This file intentionally contains no code.
4*----------------------------------------------------------------------------*/
5
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_extF80MToCommonNaN.c deleted-5
...@@ -1,5 +0,0 @@
1
2/*----------------------------------------------------------------------------
3| This file intentionally contains no code.
4*----------------------------------------------------------------------------*/
5
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_extF80UIToCommonNaN.c deleted-5
...@@ -1,5 +0,0 @@
1
2/*----------------------------------------------------------------------------
3| This file intentionally contains no code.
4*----------------------------------------------------------------------------*/
5
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_f128MToCommonNaN.c deleted-5
...@@ -1,5 +0,0 @@
1
2/*----------------------------------------------------------------------------
3| This file intentionally contains no code.
4*----------------------------------------------------------------------------*/
5
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_f128UIToCommonNaN.c deleted-5
...@@ -1,5 +0,0 @@
1
2/*----------------------------------------------------------------------------
3| This file intentionally contains no code.
4*----------------------------------------------------------------------------*/
5
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_f16UIToCommonNaN.c deleted-5
...@@ -1,5 +0,0 @@
1
2/*----------------------------------------------------------------------------
3| This file intentionally contains no code.
4*----------------------------------------------------------------------------*/
5
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_f32UIToCommonNaN.c deleted-5
...@@ -1,5 +0,0 @@
1
2/*----------------------------------------------------------------------------
3| This file intentionally contains no code.
4*----------------------------------------------------------------------------*/
5
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_f64UIToCommonNaN.c deleted-5
...@@ -1,5 +0,0 @@
1
2/*----------------------------------------------------------------------------
3| This file intentionally contains no code.
4*----------------------------------------------------------------------------*/
5
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_propagateNaNExtF80M.c deleted-74
...@@ -1,74 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44| Assuming at least one of the two 80-bit extended floating-point values
45| pointed to by 'aSPtr' and 'bSPtr' is a NaN, stores the combined NaN result
46| at the location pointed to by 'zSPtr'. If either original floating-point
47| value is a signaling NaN, the invalid exception is raised.
48*----------------------------------------------------------------------------*/
49void
50 softfloat_propagateNaNExtF80M(
51 const struct extFloat80M *aSPtr,
52 const struct extFloat80M *bSPtr,
53 struct extFloat80M *zSPtr
54 )
55{
56 uint_fast16_t ui64;
57 uint_fast64_t ui0;
58
59 ui64 = aSPtr->signExp;
60 ui0 = aSPtr->signif;
61 if (
62 softfloat_isSigNaNExtF80UI( ui64, ui0 )
63 || (bSPtr
64 && (ui64 = bSPtr->signExp,
65 ui0 = bSPtr->signif,
66 softfloat_isSigNaNExtF80UI( ui64, ui0 )))
67 ) {
68 softfloat_raiseFlags( softfloat_flag_invalid );
69 }
70 zSPtr->signExp = defaultNaNExtF80UI64;
71 zSPtr->signif = defaultNaNExtF80UI0;
72
73}
74
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_propagateNaNExtF80UI.c deleted-73
...@@ -1,73 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44| Interpreting the unsigned integer formed from concatenating 'uiA64' and
45| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting
46| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
47| 80-bit extended floating-point value, and assuming at least on of these
48| floating-point values is a NaN, returns the bit pattern of the combined NaN
49| result. If either original floating-point value is a signaling NaN, the
50| invalid exception is raised.
51*----------------------------------------------------------------------------*/
52struct uint128
53 softfloat_propagateNaNExtF80UI(
54 uint_fast16_t uiA64,
55 uint_fast64_t uiA0,
56 uint_fast16_t uiB64,
57 uint_fast64_t uiB0
58 )
59{
60 struct uint128 uiZ;
61
62 if (
63 softfloat_isSigNaNExtF80UI( uiA64, uiA0 )
64 || softfloat_isSigNaNExtF80UI( uiB64, uiB0 )
65 ) {
66 softfloat_raiseFlags( softfloat_flag_invalid );
67 }
68 uiZ.v64 = defaultNaNExtF80UI64;
69 uiZ.v0 = defaultNaNExtF80UI0;
70 return uiZ;
71
72}
73
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_propagateNaNF128M.c deleted-68
...@@ -1,68 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44| Assuming at least one of the two 128-bit floating-point values pointed to by
45| 'aWPtr' and 'bWPtr' is a NaN, stores the combined NaN result at the location
46| pointed to by 'zWPtr'. If either original floating-point value is a
47| signaling NaN, the invalid exception is raised. Each of 'aWPtr', 'bWPtr',
48| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
49| the platform's normal endian order to form a 128-bit floating-point value.
50*----------------------------------------------------------------------------*/
51void
52 softfloat_propagateNaNF128M(
53 const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr )
54{
55
56 if (
57 f128M_isSignalingNaN( (const float128_t *) aWPtr );
58 || (bWPtr && f128M_isSignalingNaN( (const float128_t *) bWPtr ))
59 ) {
60 softfloat_raiseFlags( softfloat_flag_invalid );
61 }
62 zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96;
63 zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64;
64 zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32;
65 zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0;
66
67}
68
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_propagateNaNF128UI.c deleted-73
...@@ -1,73 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44| Interpreting the unsigned integer formed from concatenating 'uiA64' and
45| 'uiA0' as a 128-bit floating-point value, and likewise interpreting the
46| unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
47| 128-bit floating-point value, and assuming at least on of these floating-
48| point values is a NaN, returns the bit pattern of the combined NaN result.
49| If either original floating-point value is a signaling NaN, the invalid
50| exception is raised.
51*----------------------------------------------------------------------------*/
52struct uint128
53 softfloat_propagateNaNF128UI(
54 uint_fast64_t uiA64,
55 uint_fast64_t uiA0,
56 uint_fast64_t uiB64,
57 uint_fast64_t uiB0
58 )
59{
60 struct uint128 uiZ;
61
62 if (
63 softfloat_isSigNaNF128UI( uiA64, uiA0 )
64 || softfloat_isSigNaNF128UI( uiB64, uiB0 )
65 ) {
66 softfloat_raiseFlags( softfloat_flag_invalid );
67 }
68 uiZ.v64 = defaultNaNF128UI64;
69 uiZ.v0 = defaultNaNF128UI0;
70 return uiZ;
71
72}
73
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_propagateNaNF16UI.c deleted-58
...@@ -1,58 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
44| point values, at least one of which is a NaN, returns the bit pattern of
45| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
46| signaling NaN, the invalid exception is raised.
47*----------------------------------------------------------------------------*/
48uint_fast16_t
49 softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB )
50{
51
52 if ( softfloat_isSigNaNF16UI( uiA ) || softfloat_isSigNaNF16UI( uiB ) ) {
53 softfloat_raiseFlags( softfloat_flag_invalid );
54 }
55 return defaultNaNF16UI;
56
57}
58
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_propagateNaNF32UI.c deleted-58
...@@ -1,58 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
44| point values, at least one of which is a NaN, returns the bit pattern of
45| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
46| signaling NaN, the invalid exception is raised.
47*----------------------------------------------------------------------------*/
48uint_fast32_t
49 softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB )
50{
51
52 if ( softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) ) {
53 softfloat_raiseFlags( softfloat_flag_invalid );
54 }
55 return defaultNaNF32UI;
56
57}
58
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/s_propagateNaNF64UI.c deleted-58
...@@ -1,58 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
44| point values, at least one of which is a NaN, returns the bit pattern of
45| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
46| signaling NaN, the invalid exception is raised.
47*----------------------------------------------------------------------------*/
48uint_fast64_t
49 softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB )
50{
51
52 if ( softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) ) {
53 softfloat_raiseFlags( softfloat_flag_invalid );
54 }
55 return defaultNaNF64UI;
56
57}
58
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/softfloat_raiseFlags.c deleted-52
...@@ -1,52 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include "platform.h"
38#include "softfloat.h"
39
40/*----------------------------------------------------------------------------
41| Raises the exceptions specified by 'flags'. Floating-point traps can be
42| defined here if desired. It is currently not possible for such a trap
43| to substitute a result value. If traps are not implemented, this routine
44| should be simply 'softfloat_exceptionFlags |= flags;'.
45*----------------------------------------------------------------------------*/
46void softfloat_raiseFlags( uint_fast8_t flags )
47{
48
49 softfloat_exceptionFlags |= flags;
50
51}
52
deps/SoftFloat-3e/source/ARM-VFPv2-defaultNaN/specialize.h deleted-407
...@@ -1,407 +0,0 @@
1
2/*============================================================================
3
4This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#ifndef specialize_h
38#define specialize_h 1
39
40#include <stdbool.h>
41#include <stdint.h>
42#include "primitiveTypes.h"
43#include "softfloat.h"
44
45/*----------------------------------------------------------------------------
46| Default value for 'softfloat_detectTininess'.
47*----------------------------------------------------------------------------*/
48#define init_detectTininess softfloat_tininess_beforeRounding
49
50/*----------------------------------------------------------------------------
51| The values to return on conversions to 32-bit integer formats that raise an
52| invalid exception.
53*----------------------------------------------------------------------------*/
54#define ui32_fromPosOverflow 0xFFFFFFFF
55#define ui32_fromNegOverflow 0
56#define ui32_fromNaN 0
57#define i32_fromPosOverflow 0x7FFFFFFF
58#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
59#define i32_fromNaN 0
60
61/*----------------------------------------------------------------------------
62| The values to return on conversions to 64-bit integer formats that raise an
63| invalid exception.
64*----------------------------------------------------------------------------*/
65#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
66#define ui64_fromNegOverflow 0
67#define ui64_fromNaN 0
68#define i64_fromPosOverflow INT64_C( 0x7FFFFFFFFFFFFFFF )
69#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
70#define i64_fromNaN 0
71
72/*----------------------------------------------------------------------------
73| "Common NaN" structure, used to transfer NaN representations from one format
74| to another.
75*----------------------------------------------------------------------------*/
76struct commonNaN { char _unused; };
77
78/*----------------------------------------------------------------------------
79| The bit pattern for a default generated 16-bit floating-point NaN.
80*----------------------------------------------------------------------------*/
81#define defaultNaNF16UI 0x7E00
82
83/*----------------------------------------------------------------------------
84| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a
85| 16-bit floating-point signaling NaN.
86| Note: This macro evaluates its argument more than once.
87*----------------------------------------------------------------------------*/
88#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF))
89
90/*----------------------------------------------------------------------------
91| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts
92| this NaN to the common NaN form, and stores the resulting common NaN at the
93| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
94| exception is raised.
95*----------------------------------------------------------------------------*/
96#define softfloat_f16UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x0200) ) softfloat_raiseFlags( softfloat_flag_invalid )
97
98/*----------------------------------------------------------------------------
99| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
100| NaN, and returns the bit pattern of this value as an unsigned integer.
101*----------------------------------------------------------------------------*/
102#define softfloat_commonNaNToF16UI( aPtr ) ((uint_fast16_t) defaultNaNF16UI)
103
104/*----------------------------------------------------------------------------
105| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
106| point values, at least one of which is a NaN, returns the bit pattern of
107| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
108| signaling NaN, the invalid exception is raised.
109*----------------------------------------------------------------------------*/
110uint_fast16_t
111 softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
112
113/*----------------------------------------------------------------------------
114| The bit pattern for a default generated 32-bit floating-point NaN.
115*----------------------------------------------------------------------------*/
116#define defaultNaNF32UI 0x7FC00000
117
118/*----------------------------------------------------------------------------
119| Returns true when 32-bit unsigned integer 'uiA' has the bit pattern of a
120| 32-bit floating-point signaling NaN.
121| Note: This macro evaluates its argument more than once.
122*----------------------------------------------------------------------------*/
123#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF))
124
125/*----------------------------------------------------------------------------
126| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts
127| this NaN to the common NaN form, and stores the resulting common NaN at the
128| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
129| exception is raised.
130*----------------------------------------------------------------------------*/
131#define softfloat_f32UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x00400000) ) softfloat_raiseFlags( softfloat_flag_invalid )
132
133/*----------------------------------------------------------------------------
134| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point
135| NaN, and returns the bit pattern of this value as an unsigned integer.
136*----------------------------------------------------------------------------*/
137#define softfloat_commonNaNToF32UI( aPtr ) ((uint_fast32_t) defaultNaNF32UI)
138
139/*----------------------------------------------------------------------------
140| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
141| point values, at least one of which is a NaN, returns the bit pattern of
142| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
143| signaling NaN, the invalid exception is raised.
144*----------------------------------------------------------------------------*/
145uint_fast32_t
146 softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
147
148/*----------------------------------------------------------------------------
149| The bit pattern for a default generated 64-bit floating-point NaN.
150*----------------------------------------------------------------------------*/
151#define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 )
152
153/*----------------------------------------------------------------------------
154| Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a
155| 64-bit floating-point signaling NaN.
156| Note: This macro evaluates its argument more than once.
157*----------------------------------------------------------------------------*/
158#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF )))
159
160/*----------------------------------------------------------------------------
161| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
162| this NaN to the common NaN form, and stores the resulting common NaN at the
163| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
164| exception is raised.
165*----------------------------------------------------------------------------*/
166#define softfloat_f64UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & UINT64_C( 0x0008000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
167
168/*----------------------------------------------------------------------------
169| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point
170| NaN, and returns the bit pattern of this value as an unsigned integer.
171*----------------------------------------------------------------------------*/
172#define softfloat_commonNaNToF64UI( aPtr ) ((uint_fast64_t) defaultNaNF64UI)
173
174/*----------------------------------------------------------------------------
175| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
176| point values, at least one of which is a NaN, returns the bit pattern of
177| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
178| signaling NaN, the invalid exception is raised.
179*----------------------------------------------------------------------------*/
180uint_fast64_t
181 softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
182
183/*----------------------------------------------------------------------------
184| The bit pattern for a default generated 80-bit extended floating-point NaN.
185*----------------------------------------------------------------------------*/
186#define defaultNaNExtF80UI64 0x7FFF
187#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 )
188
189/*----------------------------------------------------------------------------
190| Returns true when the 80-bit unsigned integer formed from concatenating
191| 16-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of an 80-bit extended
192| floating-point signaling NaN.
193| Note: This macro evaluates its arguments more than once.
194*----------------------------------------------------------------------------*/
195#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
196
197#ifdef SOFTFLOAT_FAST_INT64
198
199/*----------------------------------------------------------------------------
200| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is
201| defined.
202*----------------------------------------------------------------------------*/
203
204/*----------------------------------------------------------------------------
205| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
206| has the bit pattern of an 80-bit extended floating-point NaN, converts
207| this NaN to the common NaN form, and stores the resulting common NaN at the
208| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
209| exception is raised.
210*----------------------------------------------------------------------------*/
211#define softfloat_extF80UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA0) & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
212
213/*----------------------------------------------------------------------------
214| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
215| floating-point NaN, and returns the bit pattern of this value as an unsigned
216| integer.
217*----------------------------------------------------------------------------*/
218#if defined INLINE && ! defined softfloat_commonNaNToExtF80UI
219INLINE
220struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr )
221{
222 struct uint128 uiZ;
223 uiZ.v64 = defaultNaNExtF80UI64;
224 uiZ.v0 = defaultNaNExtF80UI0;
225 return uiZ;
226}
227#else
228struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
229#endif
230
231/*----------------------------------------------------------------------------
232| Interpreting the unsigned integer formed from concatenating 'uiA64' and
233| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting
234| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
235| 80-bit extended floating-point value, and assuming at least on of these
236| floating-point values is a NaN, returns the bit pattern of the combined NaN
237| result. If either original floating-point value is a signaling NaN, the
238| invalid exception is raised.
239*----------------------------------------------------------------------------*/
240struct uint128
241 softfloat_propagateNaNExtF80UI(
242 uint_fast16_t uiA64,
243 uint_fast64_t uiA0,
244 uint_fast16_t uiB64,
245 uint_fast64_t uiB0
246 );
247
248/*----------------------------------------------------------------------------
249| The bit pattern for a default generated 128-bit floating-point NaN.
250*----------------------------------------------------------------------------*/
251#define defaultNaNF128UI64 UINT64_C( 0x7FFF800000000000 )
252#define defaultNaNF128UI0 UINT64_C( 0 )
253
254/*----------------------------------------------------------------------------
255| Returns true when the 128-bit unsigned integer formed from concatenating
256| 64-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of a 128-bit floating-
257| point signaling NaN.
258| Note: This macro evaluates its arguments more than once.
259*----------------------------------------------------------------------------*/
260#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
261
262/*----------------------------------------------------------------------------
263| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
264| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to
265| the common NaN form, and stores the resulting common NaN at the location
266| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
267| is raised.
268*----------------------------------------------------------------------------*/
269#define softfloat_f128UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA64) & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
270
271/*----------------------------------------------------------------------------
272| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
273| NaN, and returns the bit pattern of this value as an unsigned integer.
274*----------------------------------------------------------------------------*/
275#if defined INLINE && ! defined softfloat_commonNaNToF128UI
276INLINE
277struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
278{
279 struct uint128 uiZ;
280 uiZ.v64 = defaultNaNF128UI64;
281 uiZ.v0 = defaultNaNF128UI0;
282 return uiZ;
283}
284#else
285struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
286#endif
287
288/*----------------------------------------------------------------------------
289| Interpreting the unsigned integer formed from concatenating 'uiA64' and
290| 'uiA0' as a 128-bit floating-point value, and likewise interpreting the
291| unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
292| 128-bit floating-point value, and assuming at least on of these floating-
293| point values is a NaN, returns the bit pattern of the combined NaN result.
294| If either original floating-point value is a signaling NaN, the invalid
295| exception is raised.
296*----------------------------------------------------------------------------*/
297struct uint128
298 softfloat_propagateNaNF128UI(
299 uint_fast64_t uiA64,
300 uint_fast64_t uiA0,
301 uint_fast64_t uiB64,
302 uint_fast64_t uiB0
303 );
304
305#else
306
307/*----------------------------------------------------------------------------
308| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is not
309| defined.
310*----------------------------------------------------------------------------*/
311
312/*----------------------------------------------------------------------------
313| Assuming the 80-bit extended floating-point value pointed to by 'aSPtr' is
314| a NaN, converts this NaN to the common NaN form, and stores the resulting
315| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
316| NaN, the invalid exception is raised.
317*----------------------------------------------------------------------------*/
318#define softfloat_extF80MToCommonNaN( aSPtr, zPtr ) if ( ! ((aSPtr)->signif & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
319
320/*----------------------------------------------------------------------------
321| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
322| floating-point NaN, and stores this NaN at the location pointed to by
323| 'zSPtr'.
324*----------------------------------------------------------------------------*/
325#if defined INLINE && ! defined softfloat_commonNaNToExtF80M
326INLINE
327void
328 softfloat_commonNaNToExtF80M(
329 const struct commonNaN *aPtr, struct extFloat80M *zSPtr )
330{
331 zSPtr->signExp = defaultNaNExtF80UI64;
332 zSPtr->signif = defaultNaNExtF80UI0;
333}
334#else
335void
336 softfloat_commonNaNToExtF80M(
337 const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
338#endif
339
340/*----------------------------------------------------------------------------
341| Assuming at least one of the two 80-bit extended floating-point values
342| pointed to by 'aSPtr' and 'bSPtr' is a NaN, stores the combined NaN result
343| at the location pointed to by 'zSPtr'. If either original floating-point
344| value is a signaling NaN, the invalid exception is raised.
345*----------------------------------------------------------------------------*/
346void
347 softfloat_propagateNaNExtF80M(
348 const struct extFloat80M *aSPtr,
349 const struct extFloat80M *bSPtr,
350 struct extFloat80M *zSPtr
351 );
352
353/*----------------------------------------------------------------------------
354| The bit pattern for a default generated 128-bit floating-point NaN.
355*----------------------------------------------------------------------------*/
356#define defaultNaNF128UI96 0x7FFF8000
357#define defaultNaNF128UI64 0
358#define defaultNaNF128UI32 0
359#define defaultNaNF128UI0 0
360
361/*----------------------------------------------------------------------------
362| Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN,
363| converts this NaN to the common NaN form, and stores the resulting common
364| NaN at the location pointed to by 'zPtr'. If the NaN is a signaling NaN,
365| the invalid exception is raised. Argument 'aWPtr' points to an array of
366| four 32-bit elements that concatenate in the platform's normal endian order
367| to form a 128-bit floating-point value.
368*----------------------------------------------------------------------------*/
369#define softfloat_f128MToCommonNaN( aWPtr, zPtr ) if ( ! ((aWPtr)[indexWordHi( 4 )] & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
370
371/*----------------------------------------------------------------------------
372| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
373| NaN, and stores this NaN at the location pointed to by 'zWPtr'. Argument
374| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
375| platform's normal endian order to form a 128-bit floating-point value.
376*----------------------------------------------------------------------------*/
377#if defined INLINE && ! defined softfloat_commonNaNToF128M
378INLINE
379void
380 softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr )
381{
382 zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96;
383 zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64;
384 zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32;
385 zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0;
386}
387#else
388void
389 softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
390#endif
391
392/*----------------------------------------------------------------------------
393| Assuming at least one of the two 128-bit floating-point values pointed to by
394| 'aWPtr' and 'bWPtr' is a NaN, stores the combined NaN result at the location
395| pointed to by 'zWPtr'. If either original floating-point value is a
396| signaling NaN, the invalid exception is raised. Each of 'aWPtr', 'bWPtr',
397| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
398| the platform's normal endian order to form a 128-bit floating-point value.
399*----------------------------------------------------------------------------*/
400void
401 softfloat_propagateNaNF128M(
402 const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
403
404#endif
405
406#endif
407
deps/SoftFloat-3e/source/ARM-VFPv2/extF80M_isSignalingNaN.c deleted-57
...@@ -1,57 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43*----------------------------------------------------------------------------*/
44bool extF80M_isSignalingNaN( const extFloat80_t *aPtr )
45{
46 const struct extFloat80M *aSPtr;
47 uint64_t uiA0;
48
49 aSPtr = (const struct extFloat80M *) aPtr;
50 if ( (aSPtr->signExp & 0x7FFF) != 0x7FFF ) return false;
51 uiA0 = aSPtr->signif;
52 return
53 ! (uiA0 & UINT64_C( 0x4000000000000000 ))
54 && (uiA0 & UINT64_C( 0x3FFFFFFFFFFFFFFF));
55
56}
57
deps/SoftFloat-3e/source/ARM-VFPv2/f128M_isSignalingNaN.c deleted-60
...@@ -1,60 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "primitives.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44*----------------------------------------------------------------------------*/
45bool f128M_isSignalingNaN( const float128_t *aPtr )
46{
47 const uint32_t *aWPtr;
48 uint32_t uiA96;
49
50 aWPtr = (const uint32_t *) aPtr;
51 uiA96 = aWPtr[indexWordHi( 4 )];
52 if ( (uiA96 & 0x7FFF8000) != 0x7FFF0000 ) return false;
53 return
54 ((uiA96 & 0x00007FFF) != 0)
55 || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
56 | aWPtr[indexWord( 4, 0 )])
57 != 0);
58
59}
60
deps/SoftFloat-3e/source/ARM-VFPv2/s_commonNaNToExtF80M.c deleted-56
...@@ -1,56 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "specialize.h"
41
42/*----------------------------------------------------------------------------
43| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
44| floating-point NaN, and stores this NaN at the location pointed to by
45| 'zSPtr'.
46*----------------------------------------------------------------------------*/
47void
48 softfloat_commonNaNToExtF80M(
49 const struct commonNaN *aPtr, struct extFloat80M *zSPtr )
50{
51
52 zSPtr->signExp = packToExtF80UI64( aPtr->sign, 0x7FFF );
53 zSPtr->signif = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1;
54
55}
56
deps/SoftFloat-3e/source/ARM-VFPv2/s_commonNaNToExtF80UI.c deleted-56
...@@ -1,56 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41
42/*----------------------------------------------------------------------------
43| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
44| floating-point NaN, and returns the bit pattern of this value as an unsigned
45| integer.
46*----------------------------------------------------------------------------*/
47struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr )
48{
49 struct uint128 uiZ;
50
51 uiZ.v64 = (uint_fast16_t) aPtr->sign<<15 | 0x7FFF;
52 uiZ.v0 = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1;
53 return uiZ;
54
55}
56
deps/SoftFloat-3e/source/ARM-VFPv2/s_commonNaNToF128M.c deleted-56
...@@ -1,56 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41
42/*----------------------------------------------------------------------------
43| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
44| NaN, and stores this NaN at the location pointed to by 'zWPtr'. Argument
45| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
46| platform's normal endian order to form a 128-bit floating-point value.
47*----------------------------------------------------------------------------*/
48void
49 softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr )
50{
51
52 softfloat_shortShiftRight128M( (const uint32_t *) &aPtr->v0, 16, zWPtr );
53 zWPtr[indexWordHi( 4 )] |= (uint32_t) aPtr->sign<<31 | 0x7FFF8000;
54
55}
56
deps/SoftFloat-3e/source/ARM-VFPv2/s_commonNaNToF128UI.c deleted-55
...@@ -1,55 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41
42/*----------------------------------------------------------------------------
43| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
44| NaN, and returns the bit pattern of this value as an unsigned integer.
45*----------------------------------------------------------------------------*/
46struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
47{
48 struct uint128 uiZ;
49
50 uiZ = softfloat_shortShiftRight128( aPtr->v64, aPtr->v0, 16 );
51 uiZ.v64 |= (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FFF800000000000 );
52 return uiZ;
53
54}
55
deps/SoftFloat-3e/source/ARM-VFPv2/s_commonNaNToF16UI.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40
41/*----------------------------------------------------------------------------
42| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
43| NaN, and returns the bit pattern of this value as an unsigned integer.
44*----------------------------------------------------------------------------*/
45uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr )
46{
47
48 return (uint_fast16_t) aPtr->sign<<15 | 0x7E00 | aPtr->v64>>54;
49
50}
51
deps/SoftFloat-3e/source/ARM-VFPv2/s_commonNaNToF32UI.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40
41/*----------------------------------------------------------------------------
42| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point
43| NaN, and returns the bit pattern of this value as an unsigned integer.
44*----------------------------------------------------------------------------*/
45uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr )
46{
47
48 return (uint_fast32_t) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41;
49
50}
51
deps/SoftFloat-3e/source/ARM-VFPv2/s_commonNaNToF64UI.c deleted-53
...@@ -1,53 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40
41/*----------------------------------------------------------------------------
42| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point
43| NaN, and returns the bit pattern of this value as an unsigned integer.
44*----------------------------------------------------------------------------*/
45uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr )
46{
47
48 return
49 (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FF8000000000000 )
50 | aPtr->v64>>12;
51
52}
53
deps/SoftFloat-3e/source/ARM-VFPv2/s_extF80MToCommonNaN.c deleted-62
...@@ -1,62 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44| Assuming the 80-bit extended floating-point value pointed to by 'aSPtr' is
45| a NaN, converts this NaN to the common NaN form, and stores the resulting
46| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
47| NaN, the invalid exception is raised.
48*----------------------------------------------------------------------------*/
49void
50 softfloat_extF80MToCommonNaN(
51 const struct extFloat80M *aSPtr, struct commonNaN *zPtr )
52{
53
54 if ( extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ) ) {
55 softfloat_raiseFlags( softfloat_flag_invalid );
56 }
57 zPtr->sign = signExtF80UI64( aSPtr->signExp );
58 zPtr->v64 = aSPtr->signif<<1;
59 zPtr->v0 = 0;
60
61}
62
deps/SoftFloat-3e/source/ARM-VFPv2/s_extF80UIToCommonNaN.c deleted-62
...@@ -1,62 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
44| has the bit pattern of an 80-bit extended floating-point NaN, converts
45| this NaN to the common NaN form, and stores the resulting common NaN at the
46| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
47| exception is raised.
48*----------------------------------------------------------------------------*/
49void
50 softfloat_extF80UIToCommonNaN(
51 uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr )
52{
53
54 if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ) {
55 softfloat_raiseFlags( softfloat_flag_invalid );
56 }
57 zPtr->sign = uiA64>>15;
58 zPtr->v64 = uiA0<<1;
59 zPtr->v0 = 0;
60
61}
62
deps/SoftFloat-3e/source/ARM-VFPv2/s_f128MToCommonNaN.c deleted-62
...@@ -1,62 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44| Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN,
45| converts this NaN to the common NaN form, and stores the resulting common
46| NaN at the location pointed to by 'zPtr'. If the NaN is a signaling NaN,
47| the invalid exception is raised. Argument 'aWPtr' points to an array of
48| four 32-bit elements that concatenate in the platform's normal endian order
49| to form a 128-bit floating-point value.
50*----------------------------------------------------------------------------*/
51void
52 softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr )
53{
54
55 if ( f128M_isSignalingNaN( (const float128_t *) aWPtr ) ) {
56 softfloat_raiseFlags( softfloat_flag_invalid );
57 }
58 zPtr->sign = aWPtr[indexWordHi( 4 )]>>31;
59 softfloat_shortShiftLeft128M( aWPtr, 16, (uint32_t *) &zPtr->v0 );
60
61}
62
deps/SoftFloat-3e/source/ARM-VFPv2/s_f128UIToCommonNaN.c deleted-65
...@@ -1,65 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43/*----------------------------------------------------------------------------
44| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
45| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to
46| the common NaN form, and stores the resulting common NaN at the location
47| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
48| is raised.
49*----------------------------------------------------------------------------*/
50void
51 softfloat_f128UIToCommonNaN(
52 uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr )
53{
54 struct uint128 NaNSig;
55
56 if ( softfloat_isSigNaNF128UI( uiA64, uiA0 ) ) {
57 softfloat_raiseFlags( softfloat_flag_invalid );
58 }
59 NaNSig = softfloat_shortShiftLeft128( uiA64, uiA0, 16 );
60 zPtr->sign = uiA64>>63;
61 zPtr->v64 = NaNSig.v64;
62 zPtr->v0 = NaNSig.v0;
63
64}
65
deps/SoftFloat-3e/source/ARM-VFPv2/s_f16UIToCommonNaN.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts
44| this NaN to the common NaN form, and stores the resulting common NaN at the
45| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
46| exception is raised.
47*----------------------------------------------------------------------------*/
48void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr )
49{
50
51 if ( softfloat_isSigNaNF16UI( uiA ) ) {
52 softfloat_raiseFlags( softfloat_flag_invalid );
53 }
54 zPtr->sign = uiA>>15;
55 zPtr->v64 = (uint_fast64_t) uiA<<54;
56 zPtr->v0 = 0;
57
58}
59
deps/SoftFloat-3e/source/ARM-VFPv2/s_f32UIToCommonNaN.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts
44| this NaN to the common NaN form, and stores the resulting common NaN at the
45| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
46| exception is raised.
47*----------------------------------------------------------------------------*/
48void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr )
49{
50
51 if ( softfloat_isSigNaNF32UI( uiA ) ) {
52 softfloat_raiseFlags( softfloat_flag_invalid );
53 }
54 zPtr->sign = uiA>>31;
55 zPtr->v64 = (uint_fast64_t) uiA<<41;
56 zPtr->v0 = 0;
57
58}
59
deps/SoftFloat-3e/source/ARM-VFPv2/s_f64UIToCommonNaN.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "specialize.h"
40#include "softfloat.h"
41
42/*----------------------------------------------------------------------------
43| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
44| this NaN to the common NaN form, and stores the resulting common NaN at the
45| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
46| exception is raised.
47*----------------------------------------------------------------------------*/
48void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr )
49{
50
51 if ( softfloat_isSigNaNF64UI( uiA ) ) {
52 softfloat_raiseFlags( softfloat_flag_invalid );
53 }
54 zPtr->sign = uiA>>63;
55 zPtr->v64 = uiA<<12;
56 zPtr->v0 = 0;
57
58}
59
deps/SoftFloat-3e/source/ARM-VFPv2/s_propagateNaNExtF80M.c deleted-86
...@@ -1,86 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Assuming at least one of the two 80-bit extended floating-point values
46| pointed to by 'aSPtr' and 'bSPtr' is a NaN, stores the combined NaN result
47| at the location pointed to by 'zSPtr'. If either original floating-point
48| value is a signaling NaN, the invalid exception is raised.
49*----------------------------------------------------------------------------*/
50void
51 softfloat_propagateNaNExtF80M(
52 const struct extFloat80M *aSPtr,
53 const struct extFloat80M *bSPtr,
54 struct extFloat80M *zSPtr
55 )
56{
57 const struct extFloat80M *sPtr;
58 bool isSigNaNA;
59 uint_fast16_t uiZ64;
60 uint_fast64_t uiZ0;
61
62 sPtr = aSPtr;
63 isSigNaNA = extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr );
64 if (
65 isSigNaNA
66 || (bSPtr
67 && extF80M_isSignalingNaN( (const extFloat80_t *) bSPtr ))
68 ) {
69 softfloat_raiseFlags( softfloat_flag_invalid );
70 if ( isSigNaNA ) goto copyNonsig;
71 goto copyNonsigB;
72 }
73 uiZ64 = sPtr->signExp;
74 uiZ0 = sPtr->signif;
75 if ( isNaNExtF80UI( uiZ64, uiZ0 ) ) goto returnNonsig;
76 copyNonsigB:
77 sPtr = bSPtr;
78 copyNonsig:
79 uiZ64 = sPtr->signExp;
80 uiZ0 = sPtr->signif;
81 returnNonsig:
82 zSPtr->signExp = uiZ64;
83 zSPtr->signif = uiZ0 | UINT64_C( 0xC000000000000000 );
84
85}
86
deps/SoftFloat-3e/source/ARM-VFPv2/s_propagateNaNExtF80UI.c deleted-83
...@@ -1,83 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting the unsigned integer formed from concatenating 'uiA64' and
46| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting
47| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
48| 80-bit extended floating-point value, and assuming at least on of these
49| floating-point values is a NaN, returns the bit pattern of the combined NaN
50| result. If either original floating-point value is a signaling NaN, the
51| invalid exception is raised.
52*----------------------------------------------------------------------------*/
53struct uint128
54 softfloat_propagateNaNExtF80UI(
55 uint_fast16_t uiA64,
56 uint_fast64_t uiA0,
57 uint_fast16_t uiB64,
58 uint_fast64_t uiB0
59 )
60{
61 bool isSigNaNA;
62 struct uint128 uiZ;
63
64 isSigNaNA = softfloat_isSigNaNExtF80UI( uiA64, uiA0 );
65 if ( isSigNaNA || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) ) {
66 softfloat_raiseFlags( softfloat_flag_invalid );
67 if ( isSigNaNA ) goto returnNonsigA;
68 goto returnNonsigB;
69 }
70 if ( isNaNExtF80UI( uiA64, uiA0 ) ) {
71 returnNonsigA:
72 uiZ.v64 = uiA64;
73 uiZ.v0 = uiA0;
74 } else {
75 returnNonsigB:
76 uiZ.v64 = uiB64;
77 uiZ.v0 = uiB0;
78 }
79 uiZ.v0 | UINT64_C( 0xC000000000000000 );
80 return uiZ;
81
82}
83
deps/SoftFloat-3e/source/ARM-VFPv2/s_propagateNaNF128M.c deleted-77
...@@ -1,77 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Assuming at least one of the two 128-bit floating-point values pointed to by
46| 'aWPtr' and 'bWPtr' is a NaN, stores the combined NaN result at the location
47| pointed to by 'zWPtr'. If either original floating-point value is a
48| signaling NaN, the invalid exception is raised. Each of 'aWPtr', 'bWPtr',
49| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
50| the platform's normal endian order to form a 128-bit floating-point value.
51*----------------------------------------------------------------------------*/
52void
53 softfloat_propagateNaNF128M(
54 const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr )
55{
56 const uint32_t *ptr;
57 bool isSigNaNA;
58
59 ptr = aWPtr;
60 isSigNaNA = f128M_isSignalingNaN( (const float128_t *) aWPtr );
61 if (
62 isSigNaNA
63 || (bWPtr && f128M_isSignalingNaN( (const float128_t *) bWPtr ))
64 ) {
65 softfloat_raiseFlags( softfloat_flag_invalid );
66 if ( ! isSigNaNA ) ptr = bWPtr;
67 goto copyNonsig;
68 }
69 if ( ! softfloat_isNaNF128M( aWPtr ) ) ptr = bWPtr;
70 copyNonsig:
71 zWPtr[indexWordHi( 4 )] = ptr[indexWordHi( 4 )] | 0x00008000;
72 zWPtr[indexWord( 4, 2 )] = ptr[indexWord( 4, 2 )];
73 zWPtr[indexWord( 4, 1 )] = ptr[indexWord( 4, 1 )];
74 zWPtr[indexWord( 4, 0 )] = ptr[indexWord( 4, 0 )];
75
76}
77
deps/SoftFloat-3e/source/ARM-VFPv2/s_propagateNaNF128UI.c deleted-83
...@@ -1,83 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting the unsigned integer formed from concatenating 'uiA64' and
46| 'uiA0' as a 128-bit floating-point value, and likewise interpreting the
47| unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
48| 128-bit floating-point value, and assuming at least on of these floating-
49| point values is a NaN, returns the bit pattern of the combined NaN result.
50| If either original floating-point value is a signaling NaN, the invalid
51| exception is raised.
52*----------------------------------------------------------------------------*/
53struct uint128
54 softfloat_propagateNaNF128UI(
55 uint_fast64_t uiA64,
56 uint_fast64_t uiA0,
57 uint_fast64_t uiB64,
58 uint_fast64_t uiB0
59 )
60{
61 bool isSigNaNA;
62 struct uint128 uiZ;
63
64 isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 );
65 if ( isSigNaNA || softfloat_isSigNaNF128UI( uiB64, uiB0 ) ) {
66 softfloat_raiseFlags( softfloat_flag_invalid );
67 if ( isSigNaNA ) goto returnNonsigA;
68 goto returnNonsigB;
69 }
70 if ( isNaNF128UI( uiA64, uiA0 ) ) {
71 returnNonsigA:
72 uiZ.v64 = uiA64;
73 uiZ.v0 = uiA0;
74 } else {
75 returnNonsigB:
76 uiZ.v64 = uiB64;
77 uiZ.v0 = uiB0;
78 }
79 uiZ.v64 |= UINT64_C( 0x0000800000000000 );
80 return uiZ;
81
82}
83
deps/SoftFloat-3e/source/ARM-VFPv2/s_propagateNaNF16UI.c deleted-63
...@@ -1,63 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
46| point values, at least one of which is a NaN, returns the bit pattern of
47| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
48| signaling NaN, the invalid exception is raised.
49*----------------------------------------------------------------------------*/
50uint_fast16_t
51 softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB )
52{
53 bool isSigNaNA;
54
55 isSigNaNA = softfloat_isSigNaNF16UI( uiA );
56 if ( isSigNaNA || softfloat_isSigNaNF16UI( uiB ) ) {
57 softfloat_raiseFlags( softfloat_flag_invalid );
58 return (isSigNaNA ? uiA : uiB) | 0x0200;
59 }
60 return isNaNF16UI( uiA ) ? uiA : uiB;
61
62}
63
deps/SoftFloat-3e/source/ARM-VFPv2/s_propagateNaNF32UI.c deleted-63
...@@ -1,63 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
46| point values, at least one of which is a NaN, returns the bit pattern of
47| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
48| signaling NaN, the invalid exception is raised.
49*----------------------------------------------------------------------------*/
50uint_fast32_t
51 softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB )
52{
53 bool isSigNaNA;
54
55 isSigNaNA = softfloat_isSigNaNF32UI( uiA );
56 if ( isSigNaNA || softfloat_isSigNaNF32UI( uiB ) ) {
57 softfloat_raiseFlags( softfloat_flag_invalid );
58 return (isSigNaNA ? uiA : uiB) | 0x00400000;
59 }
60 return isNaNF32UI( uiA ) ? uiA : uiB;
61
62}
63
deps/SoftFloat-3e/source/ARM-VFPv2/s_propagateNaNF64UI.c deleted-63
...@@ -1,63 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44/*----------------------------------------------------------------------------
45| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
46| point values, at least one of which is a NaN, returns the bit pattern of
47| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
48| signaling NaN, the invalid exception is raised.
49*----------------------------------------------------------------------------*/
50uint_fast64_t
51 softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB )
52{
53 bool isSigNaNA;
54
55 isSigNaNA = softfloat_isSigNaNF64UI( uiA );
56 if ( isSigNaNA || softfloat_isSigNaNF64UI( uiB ) ) {
57 softfloat_raiseFlags( softfloat_flag_invalid );
58 return (isSigNaNA ? uiA : uiB) | UINT64_C( 0x0008000000000000 );
59 }
60 return isNaNF64UI( uiA ) ? uiA : uiB;
61
62}
63
deps/SoftFloat-3e/source/ARM-VFPv2/softfloat_raiseFlags.c deleted-52
...@@ -1,52 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include "platform.h"
38#include "softfloat.h"
39
40/*----------------------------------------------------------------------------
41| Raises the exceptions specified by 'flags'. Floating-point traps can be
42| defined here if desired. It is currently not possible for such a trap
43| to substitute a result value. If traps are not implemented, this routine
44| should be simply 'softfloat_exceptionFlags |= flags;'.
45*----------------------------------------------------------------------------*/
46void softfloat_raiseFlags( uint_fast8_t flags )
47{
48
49 softfloat_exceptionFlags |= flags;
50
51}
52
deps/SoftFloat-3e/source/ARM-VFPv2/specialize.h deleted-376
...@@ -1,376 +0,0 @@
1
2/*============================================================================
3
4This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#ifndef specialize_h
38#define specialize_h 1
39
40#include <stdbool.h>
41#include <stdint.h>
42#include "primitiveTypes.h"
43#include "softfloat.h"
44
45/*----------------------------------------------------------------------------
46| Default value for 'softfloat_detectTininess'.
47*----------------------------------------------------------------------------*/
48#define init_detectTininess softfloat_tininess_beforeRounding
49
50/*----------------------------------------------------------------------------
51| The values to return on conversions to 32-bit integer formats that raise an
52| invalid exception.
53*----------------------------------------------------------------------------*/
54#define ui32_fromPosOverflow 0xFFFFFFFF
55#define ui32_fromNegOverflow 0
56#define ui32_fromNaN 0
57#define i32_fromPosOverflow 0x7FFFFFFF
58#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
59#define i32_fromNaN 0
60
61/*----------------------------------------------------------------------------
62| The values to return on conversions to 64-bit integer formats that raise an
63| invalid exception.
64*----------------------------------------------------------------------------*/
65#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
66#define ui64_fromNegOverflow 0
67#define ui64_fromNaN 0
68#define i64_fromPosOverflow INT64_C( 0x7FFFFFFFFFFFFFFF )
69#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
70#define i64_fromNaN 0
71
72/*----------------------------------------------------------------------------
73| "Common NaN" structure, used to transfer NaN representations from one format
74| to another.
75*----------------------------------------------------------------------------*/
76struct commonNaN {
77 bool sign;
78#ifdef LITTLEENDIAN
79 uint64_t v0, v64;
80#else
81 uint64_t v64, v0;
82#endif
83};
84
85/*----------------------------------------------------------------------------
86| The bit pattern for a default generated 16-bit floating-point NaN.
87*----------------------------------------------------------------------------*/
88#define defaultNaNF16UI 0x7E00
89
90/*----------------------------------------------------------------------------
91| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a
92| 16-bit floating-point signaling NaN.
93| Note: This macro evaluates its argument more than once.
94*----------------------------------------------------------------------------*/
95#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF))
96
97/*----------------------------------------------------------------------------
98| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts
99| this NaN to the common NaN form, and stores the resulting common NaN at the
100| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
101| exception is raised.
102*----------------------------------------------------------------------------*/
103void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr );
104
105/*----------------------------------------------------------------------------
106| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
107| NaN, and returns the bit pattern of this value as an unsigned integer.
108*----------------------------------------------------------------------------*/
109uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
110
111/*----------------------------------------------------------------------------
112| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
113| point values, at least one of which is a NaN, returns the bit pattern of
114| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
115| signaling NaN, the invalid exception is raised.
116*----------------------------------------------------------------------------*/
117uint_fast16_t
118 softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
119
120/*----------------------------------------------------------------------------
121| The bit pattern for a default generated 32-bit floating-point NaN.
122*----------------------------------------------------------------------------*/
123#define defaultNaNF32UI 0x7FC00000
124
125/*----------------------------------------------------------------------------
126| Returns true when 32-bit unsigned integer 'uiA' has the bit pattern of a
127| 32-bit floating-point signaling NaN.
128| Note: This macro evaluates its argument more than once.
129*----------------------------------------------------------------------------*/
130#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF))
131
132/*----------------------------------------------------------------------------
133| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts
134| this NaN to the common NaN form, and stores the resulting common NaN at the
135| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
136| exception is raised.
137*----------------------------------------------------------------------------*/
138void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr );
139
140/*----------------------------------------------------------------------------
141| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point
142| NaN, and returns the bit pattern of this value as an unsigned integer.
143*----------------------------------------------------------------------------*/
144uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
145
146/*----------------------------------------------------------------------------
147| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
148| point values, at least one of which is a NaN, returns the bit pattern of
149| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
150| signaling NaN, the invalid exception is raised.
151*----------------------------------------------------------------------------*/
152uint_fast32_t
153 softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
154
155/*----------------------------------------------------------------------------
156| The bit pattern for a default generated 64-bit floating-point NaN.
157*----------------------------------------------------------------------------*/
158#define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 )
159
160/*----------------------------------------------------------------------------
161| Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a
162| 64-bit floating-point signaling NaN.
163| Note: This macro evaluates its argument more than once.
164*----------------------------------------------------------------------------*/
165#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF )))
166
167/*----------------------------------------------------------------------------
168| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
169| this NaN to the common NaN form, and stores the resulting common NaN at the
170| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
171| exception is raised.
172*----------------------------------------------------------------------------*/
173void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr );
174
175/*----------------------------------------------------------------------------
176| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point
177| NaN, and returns the bit pattern of this value as an unsigned integer.
178*----------------------------------------------------------------------------*/
179uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
180
181/*----------------------------------------------------------------------------
182| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
183| point values, at least one of which is a NaN, returns the bit pattern of
184| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
185| signaling NaN, the invalid exception is raised.
186*----------------------------------------------------------------------------*/
187uint_fast64_t
188 softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
189
190/*----------------------------------------------------------------------------
191| The bit pattern for a default generated 80-bit extended floating-point NaN.
192*----------------------------------------------------------------------------*/
193#define defaultNaNExtF80UI64 0x7FFF
194#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 )
195
196/*----------------------------------------------------------------------------
197| Returns true when the 80-bit unsigned integer formed from concatenating
198| 16-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of an 80-bit extended
199| floating-point signaling NaN.
200| Note: This macro evaluates its arguments more than once.
201*----------------------------------------------------------------------------*/
202#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
203
204#ifdef SOFTFLOAT_FAST_INT64
205
206/*----------------------------------------------------------------------------
207| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is
208| defined.
209*----------------------------------------------------------------------------*/
210
211/*----------------------------------------------------------------------------
212| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
213| has the bit pattern of an 80-bit extended floating-point NaN, converts
214| this NaN to the common NaN form, and stores the resulting common NaN at the
215| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
216| exception is raised.
217*----------------------------------------------------------------------------*/
218void
219 softfloat_extF80UIToCommonNaN(
220 uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
221
222/*----------------------------------------------------------------------------
223| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
224| floating-point NaN, and returns the bit pattern of this value as an unsigned
225| integer.
226*----------------------------------------------------------------------------*/
227struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
228
229/*----------------------------------------------------------------------------
230| Interpreting the unsigned integer formed from concatenating 'uiA64' and
231| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting
232| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
233| 80-bit extended floating-point value, and assuming at least on of these
234| floating-point values is a NaN, returns the bit pattern of the combined NaN
235| result. If either original floating-point value is a signaling NaN, the
236| invalid exception is raised.
237*----------------------------------------------------------------------------*/
238struct uint128
239 softfloat_propagateNaNExtF80UI(
240 uint_fast16_t uiA64,
241 uint_fast64_t uiA0,
242 uint_fast16_t uiB64,
243 uint_fast64_t uiB0
244 );
245
246/*----------------------------------------------------------------------------
247| The bit pattern for a default generated 128-bit floating-point NaN.
248*----------------------------------------------------------------------------*/
249#define defaultNaNF128UI64 UINT64_C( 0x7FFF800000000000 )
250#define defaultNaNF128UI0 UINT64_C( 0 )
251
252/*----------------------------------------------------------------------------
253| Returns true when the 128-bit unsigned integer formed from concatenating
254| 64-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of a 128-bit floating-
255| point signaling NaN.
256| Note: This macro evaluates its arguments more than once.
257*----------------------------------------------------------------------------*/
258#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
259
260/*----------------------------------------------------------------------------
261| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
262| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to
263| the common NaN form, and stores the resulting common NaN at the location
264| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
265| is raised.
266*----------------------------------------------------------------------------*/
267void
268 softfloat_f128UIToCommonNaN(
269 uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
270
271/*----------------------------------------------------------------------------
272| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
273| NaN, and returns the bit pattern of this value as an unsigned integer.
274*----------------------------------------------------------------------------*/
275struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
276
277/*----------------------------------------------------------------------------
278| Interpreting the unsigned integer formed from concatenating 'uiA64' and
279| 'uiA0' as a 128-bit floating-point value, and likewise interpreting the
280| unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
281| 128-bit floating-point value, and assuming at least on of these floating-
282| point values is a NaN, returns the bit pattern of the combined NaN result.
283| If either original floating-point value is a signaling NaN, the invalid
284| exception is raised.
285*----------------------------------------------------------------------------*/
286struct uint128
287 softfloat_propagateNaNF128UI(
288 uint_fast64_t uiA64,
289 uint_fast64_t uiA0,
290 uint_fast64_t uiB64,
291 uint_fast64_t uiB0
292 );
293
294#else
295
296/*----------------------------------------------------------------------------
297| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is not
298| defined.
299*----------------------------------------------------------------------------*/
300
301/*----------------------------------------------------------------------------
302| Assuming the 80-bit extended floating-point value pointed to by 'aSPtr' is
303| a NaN, converts this NaN to the common NaN form, and stores the resulting
304| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
305| NaN, the invalid exception is raised.
306*----------------------------------------------------------------------------*/
307void
308 softfloat_extF80MToCommonNaN(
309 const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
310
311/*----------------------------------------------------------------------------
312| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
313| floating-point NaN, and stores this NaN at the location pointed to by
314| 'zSPtr'.
315*----------------------------------------------------------------------------*/
316void
317 softfloat_commonNaNToExtF80M(
318 const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
319
320/*----------------------------------------------------------------------------
321| Assuming at least one of the two 80-bit extended floating-point values
322| pointed to by 'aSPtr' and 'bSPtr' is a NaN, stores the combined NaN result
323| at the location pointed to by 'zSPtr'. If either original floating-point
324| value is a signaling NaN, the invalid exception is raised.
325*----------------------------------------------------------------------------*/
326void
327 softfloat_propagateNaNExtF80M(
328 const struct extFloat80M *aSPtr,
329 const struct extFloat80M *bSPtr,
330 struct extFloat80M *zSPtr
331 );
332
333/*----------------------------------------------------------------------------
334| The bit pattern for a default generated 128-bit floating-point NaN.
335*----------------------------------------------------------------------------*/
336#define defaultNaNF128UI96 0x7FFF8000
337#define defaultNaNF128UI64 0
338#define defaultNaNF128UI32 0
339#define defaultNaNF128UI0 0
340
341/*----------------------------------------------------------------------------
342| Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN,
343| converts this NaN to the common NaN form, and stores the resulting common
344| NaN at the location pointed to by 'zPtr'. If the NaN is a signaling NaN,
345| the invalid exception is raised. Argument 'aWPtr' points to an array of
346| four 32-bit elements that concatenate in the platform's normal endian order
347| to form a 128-bit floating-point value.
348*----------------------------------------------------------------------------*/
349void
350 softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
351
352/*----------------------------------------------------------------------------
353| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
354| NaN, and stores this NaN at the location pointed to by 'zWPtr'. Argument
355| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
356| platform's normal endian order to form a 128-bit floating-point value.
357*----------------------------------------------------------------------------*/
358void
359 softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
360
361/*----------------------------------------------------------------------------
362| Assuming at least one of the two 128-bit floating-point values pointed to by
363| 'aWPtr' and 'bWPtr' is a NaN, stores the combined NaN result at the location
364| pointed to by 'zWPtr'. If either original floating-point value is a
365| signaling NaN, the invalid exception is raised. Each of 'aWPtr', 'bWPtr',
366| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
367| the platform's normal endian order to form a 128-bit floating-point value.
368*----------------------------------------------------------------------------*/
369void
370 softfloat_propagateNaNF128M(
371 const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
372
373#endif
374
375#endif
376
deps/SoftFloat-3e/source/extF80M_add.c deleted-100
...@@ -1,100 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42#ifdef SOFTFLOAT_FAST_INT64
43
44void
45 extF80M_add(
46 const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
47{
48 const struct extFloat80M *aSPtr, *bSPtr;
49 uint_fast16_t uiA64;
50 uint_fast64_t uiA0;
51 bool signA;
52 uint_fast16_t uiB64;
53 uint_fast64_t uiB0;
54 bool signB;
55#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
56 extFloat80_t
57 (*magsFuncPtr)(
58 uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool );
59#endif
60
61 aSPtr = (const struct extFloat80M *) aPtr;
62 bSPtr = (const struct extFloat80M *) bPtr;
63 uiA64 = aSPtr->signExp;
64 uiA0 = aSPtr->signif;
65 signA = signExtF80UI64( uiA64 );
66 uiB64 = bSPtr->signExp;
67 uiB0 = bSPtr->signif;
68 signB = signExtF80UI64( uiB64 );
69#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
70 if ( signA == signB ) {
71 *zPtr = softfloat_addMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA );
72 } else {
73 *zPtr = softfloat_subMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA );
74 }
75#else
76 magsFuncPtr =
77 (signA == signB) ? softfloat_addMagsExtF80 : softfloat_subMagsExtF80;
78 *zPtr = (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
79#endif
80
81}
82
83#else
84
85void
86 extF80M_add(
87 const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
88{
89
90 softfloat_addExtF80M(
91 (const struct extFloat80M *) aPtr,
92 (const struct extFloat80M *) bPtr,
93 (struct extFloat80M *) zPtr,
94 false
95 );
96
97}
98
99#endif
100
deps/SoftFloat-3e/source/extF80M_div.c deleted-194
...@@ -1,194 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void
47 extF80M_div(
48 const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
49{
50
51 *zPtr = extF80_div( *aPtr, *bPtr );
52
53}
54
55#else
56
57void
58 extF80M_div(
59 const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
60{
61 const struct extFloat80M *aSPtr, *bSPtr;
62 struct extFloat80M *zSPtr;
63 uint_fast16_t uiA64;
64 int32_t expA;
65 uint_fast16_t uiB64;
66 int32_t expB;
67 bool signZ;
68 uint64_t sigA, x64;
69 int32_t expZ;
70 int shiftDist;
71 uint32_t y[3], recip32, sigB[3];
72 int ix;
73 uint32_t q, qs[2];
74 uint_fast16_t uiZ64;
75 uint64_t uiZ0;
76
77 /*------------------------------------------------------------------------
78 *------------------------------------------------------------------------*/
79 aSPtr = (const struct extFloat80M *) aPtr;
80 bSPtr = (const struct extFloat80M *) bPtr;
81 zSPtr = (struct extFloat80M *) zPtr;
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 uiA64 = aSPtr->signExp;
85 expA = expExtF80UI64( uiA64 );
86 uiB64 = bSPtr->signExp;
87 expB = expExtF80UI64( uiB64 );
88 signZ = signExtF80UI64( uiA64 ) ^ signExtF80UI64( uiB64 );
89 /*------------------------------------------------------------------------
90 *------------------------------------------------------------------------*/
91 if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
92 if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return;
93 if ( expA == 0x7FFF ) {
94 if ( expB == 0x7FFF ) goto invalid;
95 goto infinity;
96 }
97 goto zero;
98 }
99 /*------------------------------------------------------------------------
100 *------------------------------------------------------------------------*/
101 sigA = aSPtr->signif;
102 x64 = bSPtr->signif;
103 if ( ! expB ) expB = 1;
104 if ( ! (x64 & UINT64_C( 0x8000000000000000 )) ) {
105 if ( ! x64 ) {
106 if ( ! sigA ) goto invalid;
107 softfloat_raiseFlags( softfloat_flag_infinite );
108 goto infinity;
109 }
110 expB += softfloat_normExtF80SigM( &x64 );
111 }
112 if ( ! expA ) expA = 1;
113 if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) {
114 if ( ! sigA ) goto zero;
115 expA += softfloat_normExtF80SigM( &sigA );
116 }
117 /*------------------------------------------------------------------------
118 *------------------------------------------------------------------------*/
119 expZ = expA - expB + 0x3FFF;
120 shiftDist = 29;
121 if ( sigA < x64 ) {
122 --expZ;
123 shiftDist = 30;
124 }
125 softfloat_shortShiftLeft64To96M( sigA, shiftDist, y );
126 recip32 = softfloat_approxRecip32_1( x64>>32 );
127 sigB[indexWord( 3, 0 )] = (uint32_t) x64<<30;
128 x64 >>= 2;
129 sigB[indexWord( 3, 2 )] = x64>>32;
130 sigB[indexWord( 3, 1 )] = x64;
131 ix = 2;
132 for (;;) {
133 x64 = (uint64_t) y[indexWordHi( 3 )] * recip32;
134 q = (x64 + 0x80000000)>>32;
135 --ix;
136 if ( ix < 0 ) break;
137 softfloat_remStep96MBy32( y, 29, sigB, q, y );
138 if ( y[indexWordHi( 3 )] & 0x80000000 ) {
139 --q;
140 softfloat_add96M( y, sigB, y );
141 }
142 qs[ix] = q;
143 }
144 /*------------------------------------------------------------------------
145 *------------------------------------------------------------------------*/
146 if ( ((q + 1) & 0x3FFFFF) < 2 ) {
147 softfloat_remStep96MBy32( y, 29, sigB, q, y );
148 if ( y[indexWordHi( 3 )] & 0x80000000 ) {
149 --q;
150 softfloat_add96M( y, sigB, y );
151 } else if ( softfloat_compare96M( sigB, y ) <= 0 ) {
152 ++q;
153 softfloat_sub96M( y, sigB, y );
154 }
155 if (
156 y[indexWordLo( 3 )] || y[indexWord( 3, 1 )] || y[indexWord( 3, 2 )]
157 ) {
158 q |= 1;
159 }
160 }
161 /*------------------------------------------------------------------------
162 *------------------------------------------------------------------------*/
163 x64 = (uint64_t) q<<9;
164 y[indexWord( 3, 0 )] = x64;
165 x64 = ((uint64_t) qs[0]<<6) + (x64>>32);
166 y[indexWord( 3, 1 )] = x64;
167 y[indexWord( 3, 2 )] = (qs[1]<<3) + (x64>>32);
168 softfloat_roundPackMToExtF80M(
169 signZ, expZ, y, extF80_roundingPrecision, zSPtr );
170 return;
171 /*------------------------------------------------------------------------
172 *------------------------------------------------------------------------*/
173 invalid:
174 softfloat_invalidExtF80M( zSPtr );
175 return;
176 /*------------------------------------------------------------------------
177 *------------------------------------------------------------------------*/
178 infinity:
179 uiZ64 = packToExtF80UI64( signZ, 0x7FFF );
180 uiZ0 = UINT64_C( 0x8000000000000000 );
181 goto uiZ;
182 /*------------------------------------------------------------------------
183 *------------------------------------------------------------------------*/
184 zero:
185 uiZ64 = packToExtF80UI64( signZ, 0 );
186 uiZ0 = 0;
187 uiZ:
188 zSPtr->signExp = uiZ64;
189 zSPtr->signif = uiZ0;
190
191}
192
193#endif
194
deps/SoftFloat-3e/source/extF80M_eq.c deleted-98
...@@ -1,98 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46bool extF80M_eq( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
47{
48
49 return extF80_eq( *aPtr, *bPtr );
50
51}
52
53#else
54
55bool extF80M_eq( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
56{
57 const struct extFloat80M *aSPtr, *bSPtr;
58 uint_fast16_t uiA64;
59 uint64_t uiA0;
60 uint_fast16_t uiB64;
61 uint64_t uiB0;
62
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 aSPtr = (const struct extFloat80M *) aPtr;
66 bSPtr = (const struct extFloat80M *) bPtr;
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 uiA64 = aSPtr->signExp;
70 uiA0 = aSPtr->signif;
71 uiB64 = bSPtr->signExp;
72 uiB0 = bSPtr->signif;
73 /*------------------------------------------------------------------------
74 *------------------------------------------------------------------------*/
75 if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
76 if (
77 softfloat_isSigNaNExtF80UI( uiA64, uiA0 )
78 || softfloat_isSigNaNExtF80UI( uiB64, uiB0 )
79 ) {
80 softfloat_raiseFlags( softfloat_flag_invalid );
81 }
82 return false;
83 }
84 /*------------------------------------------------------------------------
85 *------------------------------------------------------------------------*/
86 if ( uiA0 == uiB0 ) {
87 return (uiA64 == uiB64) || ! uiA0;
88 } else {
89 if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) {
90 return ! softfloat_compareNonnormExtF80M( aSPtr, bSPtr );
91 }
92 return false;
93 }
94
95}
96
97#endif
98
deps/SoftFloat-3e/source/extF80M_eq_signaling.c deleted-92
...@@ -1,92 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43#ifdef SOFTFLOAT_FAST_INT64
44
45bool extF80M_eq_signaling( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
46{
47
48 return extF80_eq_signaling( *aPtr, *bPtr );
49
50}
51
52#else
53
54bool extF80M_eq_signaling( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
55{
56 const struct extFloat80M *aSPtr, *bSPtr;
57 uint_fast16_t uiA64;
58 uint64_t uiA0;
59 uint_fast16_t uiB64;
60 uint64_t uiB0;
61
62 /*------------------------------------------------------------------------
63 *------------------------------------------------------------------------*/
64 aSPtr = (const struct extFloat80M *) aPtr;
65 bSPtr = (const struct extFloat80M *) bPtr;
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 uiA64 = aSPtr->signExp;
69 uiA0 = aSPtr->signif;
70 uiB64 = bSPtr->signExp;
71 uiB0 = bSPtr->signif;
72 /*------------------------------------------------------------------------
73 *------------------------------------------------------------------------*/
74 if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
75 softfloat_raiseFlags( softfloat_flag_invalid );
76 return false;
77 }
78 /*------------------------------------------------------------------------
79 *------------------------------------------------------------------------*/
80 if ( uiA0 == uiB0 ) {
81 return (uiA64 == uiB64) || ! uiA0;
82 } else {
83 if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) {
84 return ! softfloat_compareNonnormExtF80M( aSPtr, bSPtr );
85 }
86 return false;
87 }
88
89}
90
91#endif
92
deps/SoftFloat-3e/source/extF80M_le.c deleted-106
...@@ -1,106 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43#ifdef SOFTFLOAT_FAST_INT64
44
45bool extF80M_le( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
46{
47
48 return extF80_le( *aPtr, *bPtr );
49
50}
51
52#else
53
54bool extF80M_le( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
55{
56 const struct extFloat80M *aSPtr, *bSPtr;
57 uint_fast16_t uiA64;
58 uint64_t uiA0;
59 uint_fast16_t uiB64;
60 uint64_t uiB0;
61 bool signA, ltMags;
62
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 aSPtr = (const struct extFloat80M *) aPtr;
66 bSPtr = (const struct extFloat80M *) bPtr;
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 uiA64 = aSPtr->signExp;
70 uiA0 = aSPtr->signif;
71 uiB64 = bSPtr->signExp;
72 uiB0 = bSPtr->signif;
73 /*------------------------------------------------------------------------
74 *------------------------------------------------------------------------*/
75 if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
76 softfloat_raiseFlags( softfloat_flag_invalid );
77 return false;
78 }
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 signA = signExtF80UI64( uiA64 );
82 if ( (uiA64 ^ uiB64) & 0x8000 ) {
83 /*--------------------------------------------------------------------
84 | Signs are different.
85 *--------------------------------------------------------------------*/
86 return signA || ! (uiA0 | uiB0);
87 } else {
88 /*--------------------------------------------------------------------
89 | Signs are the same.
90 *--------------------------------------------------------------------*/
91 if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) {
92 return (softfloat_compareNonnormExtF80M( aSPtr, bSPtr ) <= 0);
93 }
94 if ( uiA64 == uiB64 ) {
95 if ( uiA0 == uiB0 ) return true;
96 ltMags = (uiA0 < uiB0);
97 } else {
98 ltMags = (uiA64 < uiB64);
99 }
100 return signA ^ ltMags;
101 }
102
103}
104
105#endif
106
deps/SoftFloat-3e/source/extF80M_le_quiet.c deleted-112
...@@ -1,112 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46bool extF80M_le_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
47{
48
49 return extF80_le_quiet( *aPtr, *bPtr );
50
51}
52
53#else
54
55bool extF80M_le_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
56{
57 const struct extFloat80M *aSPtr, *bSPtr;
58 uint_fast16_t uiA64;
59 uint64_t uiA0;
60 uint_fast16_t uiB64;
61 uint64_t uiB0;
62 bool signA, ltMags;
63
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 aSPtr = (const struct extFloat80M *) aPtr;
67 bSPtr = (const struct extFloat80M *) bPtr;
68 /*------------------------------------------------------------------------
69 *------------------------------------------------------------------------*/
70 uiA64 = aSPtr->signExp;
71 uiA0 = aSPtr->signif;
72 uiB64 = bSPtr->signExp;
73 uiB0 = bSPtr->signif;
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
77 if (
78 softfloat_isSigNaNExtF80UI( uiA64, uiA0 )
79 || softfloat_isSigNaNExtF80UI( uiB64, uiB0 )
80 ) {
81 softfloat_raiseFlags( softfloat_flag_invalid );
82 }
83 return false;
84 }
85 /*------------------------------------------------------------------------
86 *------------------------------------------------------------------------*/
87 signA = signExtF80UI64( uiA64 );
88 if ( (uiA64 ^ uiB64) & 0x8000 ) {
89 /*--------------------------------------------------------------------
90 | Signs are different.
91 *--------------------------------------------------------------------*/
92 return signA || ! (uiA0 | uiB0);
93 } else {
94 /*--------------------------------------------------------------------
95 | Signs are the same.
96 *--------------------------------------------------------------------*/
97 if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) {
98 return (softfloat_compareNonnormExtF80M( aSPtr, bSPtr ) <= 0);
99 }
100 if ( uiA64 == uiB64 ) {
101 if ( uiA0 == uiB0 ) return true;
102 ltMags = (uiA0 < uiB0);
103 } else {
104 ltMags = (uiA64 < uiB64);
105 }
106 return signA ^ ltMags;
107 }
108
109}
110
111#endif
112
deps/SoftFloat-3e/source/extF80M_lt.c deleted-106
...@@ -1,106 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43#ifdef SOFTFLOAT_FAST_INT64
44
45bool extF80M_lt( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
46{
47
48 return extF80_lt( *aPtr, *bPtr );
49
50}
51
52#else
53
54bool extF80M_lt( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
55{
56 const struct extFloat80M *aSPtr, *bSPtr;
57 uint_fast16_t uiA64;
58 uint64_t uiA0;
59 uint_fast16_t uiB64;
60 uint64_t uiB0;
61 bool signA, ltMags;
62
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 aSPtr = (const struct extFloat80M *) aPtr;
66 bSPtr = (const struct extFloat80M *) bPtr;
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 uiA64 = aSPtr->signExp;
70 uiA0 = aSPtr->signif;
71 uiB64 = bSPtr->signExp;
72 uiB0 = bSPtr->signif;
73 /*------------------------------------------------------------------------
74 *------------------------------------------------------------------------*/
75 if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
76 softfloat_raiseFlags( softfloat_flag_invalid );
77 return false;
78 }
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 signA = signExtF80UI64( uiA64 );
82 if ( (uiA64 ^ uiB64) & 0x8000 ) {
83 /*--------------------------------------------------------------------
84 | Signs are different.
85 *--------------------------------------------------------------------*/
86 return signA && ((uiA0 | uiB0) != 0);
87 } else {
88 /*--------------------------------------------------------------------
89 | Signs are the same.
90 *--------------------------------------------------------------------*/
91 if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) {
92 return (softfloat_compareNonnormExtF80M( aSPtr, bSPtr ) < 0);
93 }
94 if ( uiA64 == uiB64 ) {
95 if ( uiA0 == uiB0 ) return false;
96 ltMags = (uiA0 < uiB0);
97 } else {
98 ltMags = (uiA64 < uiB64);
99 }
100 return signA ^ ltMags;
101 }
102
103}
104
105#endif
106
deps/SoftFloat-3e/source/extF80M_lt_quiet.c deleted-112
...@@ -1,112 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46bool extF80M_lt_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
47{
48
49 return extF80_lt_quiet( *aPtr, *bPtr );
50
51}
52
53#else
54
55bool extF80M_lt_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
56{
57 const struct extFloat80M *aSPtr, *bSPtr;
58 uint_fast16_t uiA64;
59 uint64_t uiA0;
60 uint_fast16_t uiB64;
61 uint64_t uiB0;
62 bool signA, ltMags;
63
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 aSPtr = (const struct extFloat80M *) aPtr;
67 bSPtr = (const struct extFloat80M *) bPtr;
68 /*------------------------------------------------------------------------
69 *------------------------------------------------------------------------*/
70 uiA64 = aSPtr->signExp;
71 uiA0 = aSPtr->signif;
72 uiB64 = bSPtr->signExp;
73 uiB0 = bSPtr->signif;
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
77 if (
78 softfloat_isSigNaNExtF80UI( uiA64, uiA0 )
79 || softfloat_isSigNaNExtF80UI( uiB64, uiB0 )
80 ) {
81 softfloat_raiseFlags( softfloat_flag_invalid );
82 }
83 return false;
84 }
85 /*------------------------------------------------------------------------
86 *------------------------------------------------------------------------*/
87 signA = signExtF80UI64( uiA64 );
88 if ( (uiA64 ^ uiB64) & 0x8000 ) {
89 /*--------------------------------------------------------------------
90 | Signs are different.
91 *--------------------------------------------------------------------*/
92 return signA && ((uiA0 | uiB0) != 0);
93 } else {
94 /*--------------------------------------------------------------------
95 | Signs are the same.
96 *--------------------------------------------------------------------*/
97 if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) {
98 return (softfloat_compareNonnormExtF80M( aSPtr, bSPtr ) < 0);
99 }
100 if ( uiA64 == uiB64 ) {
101 if ( uiA0 == uiB0 ) return false;
102 ltMags = (uiA0 < uiB0);
103 } else {
104 ltMags = (uiA64 < uiB64);
105 }
106 return signA ^ ltMags;
107 }
108
109}
110
111#endif
112
deps/SoftFloat-3e/source/extF80M_mul.c deleted-139
...@@ -1,139 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void
47 extF80M_mul(
48 const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
49{
50
51 *zPtr = extF80_mul( *aPtr, *bPtr );
52
53}
54
55#else
56
57void
58 extF80M_mul(
59 const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
60{
61 const struct extFloat80M *aSPtr, *bSPtr;
62 struct extFloat80M *zSPtr;
63 uint_fast16_t uiA64;
64 int32_t expA;
65 uint_fast16_t uiB64;
66 int32_t expB;
67 bool signZ;
68 uint_fast16_t exp, uiZ64;
69 uint64_t uiZ0, sigA, sigB;
70 int32_t expZ;
71 uint32_t sigProd[4], *extSigZPtr;
72
73 /*------------------------------------------------------------------------
74 *------------------------------------------------------------------------*/
75 aSPtr = (const struct extFloat80M *) aPtr;
76 bSPtr = (const struct extFloat80M *) bPtr;
77 zSPtr = (struct extFloat80M *) zPtr;
78 /*------------------------------------------------------------------------
79 *------------------------------------------------------------------------*/
80 uiA64 = aSPtr->signExp;
81 expA = expExtF80UI64( uiA64 );
82 uiB64 = bSPtr->signExp;
83 expB = expExtF80UI64( uiB64 );
84 signZ = signExtF80UI64( uiA64 ) ^ signExtF80UI64( uiB64 );
85 /*------------------------------------------------------------------------
86 *------------------------------------------------------------------------*/
87 if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
88 if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return;
89 if (
90 (! aSPtr->signif && (expA != 0x7FFF))
91 || (! bSPtr->signif && (expB != 0x7FFF))
92 ) {
93 softfloat_invalidExtF80M( zSPtr );
94 return;
95 }
96 uiZ64 = packToExtF80UI64( signZ, 0x7FFF );
97 uiZ0 = UINT64_C( 0x8000000000000000 );
98 goto uiZ;
99 }
100 /*------------------------------------------------------------------------
101 *------------------------------------------------------------------------*/
102 if ( ! expA ) expA = 1;
103 sigA = aSPtr->signif;
104 if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) {
105 if ( ! sigA ) goto zero;
106 expA += softfloat_normExtF80SigM( &sigA );
107 }
108 if ( ! expB ) expB = 1;
109 sigB = bSPtr->signif;
110 if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) {
111 if ( ! sigB ) goto zero;
112 expB += softfloat_normExtF80SigM( &sigB );
113 }
114 /*------------------------------------------------------------------------
115 *------------------------------------------------------------------------*/
116 expZ = expA + expB - 0x3FFE;
117 softfloat_mul64To128M( sigA, sigB, sigProd );
118 if ( sigProd[indexWordLo( 4 )] ) sigProd[indexWord( 4, 1 )] |= 1;
119 extSigZPtr = &sigProd[indexMultiwordHi( 4, 3 )];
120 if ( sigProd[indexWordHi( 4 )] < 0x80000000 ) {
121 --expZ;
122 softfloat_add96M( extSigZPtr, extSigZPtr, extSigZPtr );
123 }
124 softfloat_roundPackMToExtF80M(
125 signZ, expZ, extSigZPtr, extF80_roundingPrecision, zSPtr );
126 return;
127 /*------------------------------------------------------------------------
128 *------------------------------------------------------------------------*/
129 zero:
130 uiZ64 = packToExtF80UI64( signZ, 0 );
131 uiZ0 = 0;
132 uiZ:
133 zSPtr->signExp = uiZ64;
134 zSPtr->signif = uiZ0;
135
136}
137
138#endif
139
deps/SoftFloat-3e/source/extF80M_rem.c deleted-204
...@@ -1,204 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void
47 extF80M_rem(
48 const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
49{
50
51 *zPtr = extF80_rem( *aPtr, *bPtr );
52
53}
54
55#else
56
57void
58 extF80M_rem(
59 const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
60{
61 const struct extFloat80M *aSPtr, *bSPtr;
62 struct extFloat80M *zSPtr;
63 uint_fast16_t uiA64;
64 int32_t expA, expB;
65 uint64_t x64;
66 bool signRem;
67 uint64_t sigA;
68 int32_t expDiff;
69 uint32_t rem[3], x[3], sig32B, q, recip32, rem2[3], *remPtr, *altRemPtr;
70 uint32_t *newRemPtr, wordMeanRem;
71
72 /*------------------------------------------------------------------------
73 *------------------------------------------------------------------------*/
74 aSPtr = (const struct extFloat80M *) aPtr;
75 bSPtr = (const struct extFloat80M *) bPtr;
76 zSPtr = (struct extFloat80M *) zPtr;
77 /*------------------------------------------------------------------------
78 *------------------------------------------------------------------------*/
79 uiA64 = aSPtr->signExp;
80 expA = expExtF80UI64( uiA64 );
81 expB = expExtF80UI64( bSPtr->signExp );
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
85 if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return;
86 if ( expA == 0x7FFF ) goto invalid;
87 /*--------------------------------------------------------------------
88 | If we get here, then argument b is an infinity and `expB' is 0x7FFF;
89 | Doubling `expB' is an easy way to ensure that `expDiff' later is
90 | less than -1, which will result in returning a canonicalized version
91 | of argument a.
92 *--------------------------------------------------------------------*/
93 expB += expB;
94 }
95 /*------------------------------------------------------------------------
96 *------------------------------------------------------------------------*/
97 if ( ! expB ) expB = 1;
98 x64 = bSPtr->signif;
99 if ( ! (x64 & UINT64_C( 0x8000000000000000 )) ) {
100 if ( ! x64 ) goto invalid;
101 expB += softfloat_normExtF80SigM( &x64 );
102 }
103 signRem = signExtF80UI64( uiA64 );
104 if ( ! expA ) expA = 1;
105 sigA = aSPtr->signif;
106 if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) {
107 if ( ! sigA ) {
108 expA = 0;
109 goto copyA;
110 }
111 expA += softfloat_normExtF80SigM( &sigA );
112 }
113 /*------------------------------------------------------------------------
114 *------------------------------------------------------------------------*/
115 expDiff = expA - expB;
116 if ( expDiff < -1 ) goto copyA;
117 rem[indexWord( 3, 2 )] = sigA>>34;
118 rem[indexWord( 3, 1 )] = sigA>>2;
119 rem[indexWord( 3, 0 )] = (uint32_t) sigA<<30;
120 x[indexWord( 3, 0 )] = (uint32_t) x64<<30;
121 sig32B = x64>>32;
122 x64 >>= 2;
123 x[indexWord( 3, 2 )] = x64>>32;
124 x[indexWord( 3, 1 )] = x64;
125 if ( expDiff < 1 ) {
126 if ( expDiff ) {
127 --expB;
128 softfloat_add96M( x, x, x );
129 q = 0;
130 } else {
131 q = (softfloat_compare96M( x, rem ) <= 0);
132 if ( q ) softfloat_sub96M( rem, x, rem );
133 }
134 } else {
135 recip32 = softfloat_approxRecip32_1( sig32B );
136 expDiff -= 30;
137 for (;;) {
138 x64 = (uint64_t) rem[indexWordHi( 3 )] * recip32;
139 if ( expDiff < 0 ) break;
140 q = (x64 + 0x80000000)>>32;
141 softfloat_remStep96MBy32( rem, 29, x, q, rem );
142 if ( rem[indexWordHi( 3 )] & 0x80000000 ) {
143 softfloat_add96M( rem, x, rem );
144 }
145 expDiff -= 29;
146 }
147 /*--------------------------------------------------------------------
148 | (`expDiff' cannot be less than -29 here.)
149 *--------------------------------------------------------------------*/
150 q = (uint32_t) (x64>>32)>>(~expDiff & 31);
151 softfloat_remStep96MBy32( rem, expDiff + 30, x, q, rem );
152 if ( rem[indexWordHi( 3 )] & 0x80000000 ) {
153 remPtr = rem;
154 altRemPtr = rem2;
155 softfloat_add96M( remPtr, x, altRemPtr );
156 goto selectRem;
157 }
158 }
159 /*------------------------------------------------------------------------
160 *------------------------------------------------------------------------*/
161 remPtr = rem;
162 altRemPtr = rem2;
163 do {
164 ++q;
165 newRemPtr = altRemPtr;
166 softfloat_sub96M( remPtr, x, newRemPtr );
167 altRemPtr = remPtr;
168 remPtr = newRemPtr;
169 } while ( ! (remPtr[indexWordHi( 3 )] & 0x80000000) );
170 selectRem:
171 softfloat_add96M( remPtr, altRemPtr, x );
172 wordMeanRem = x[indexWordHi( 3 )];
173 if (
174 (wordMeanRem & 0x80000000)
175 || (! wordMeanRem && (q & 1) && ! x[indexWord( 3, 0 )]
176 && ! x[indexWord( 3, 1 )])
177 ) {
178 remPtr = altRemPtr;
179 }
180 if ( remPtr[indexWordHi( 3 )] & 0x80000000 ) {
181 signRem = ! signRem;
182 softfloat_negX96M( remPtr );
183 }
184 softfloat_normRoundPackMToExtF80M( signRem, expB + 2, remPtr, 80, zSPtr );
185 return;
186 /*------------------------------------------------------------------------
187 *------------------------------------------------------------------------*/
188 invalid:
189 softfloat_invalidExtF80M( zSPtr );
190 return;
191 /*------------------------------------------------------------------------
192 *------------------------------------------------------------------------*/
193 copyA:
194 if ( expA < 1 ) {
195 sigA >>= 1 - expA;
196 expA = 0;
197 }
198 zSPtr->signExp = packToExtF80UI64( signRem, expA );
199 zSPtr->signif = sigA;
200
201}
202
203#endif
204
deps/SoftFloat-3e/source/extF80M_roundToInt.c deleted-176
...@@ -1,176 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void
47 extF80M_roundToInt(
48 const extFloat80_t *aPtr,
49 uint_fast8_t roundingMode,
50 bool exact,
51 extFloat80_t *zPtr
52 )
53{
54
55 *zPtr = extF80_roundToInt( *aPtr, roundingMode, exact );
56
57}
58
59#else
60
61void
62 extF80M_roundToInt(
63 const extFloat80_t *aPtr,
64 uint_fast8_t roundingMode,
65 bool exact,
66 extFloat80_t *zPtr
67 )
68{
69 const struct extFloat80M *aSPtr;
70 struct extFloat80M *zSPtr;
71 uint_fast16_t uiA64, signUI64;
72 int32_t exp;
73 uint64_t sigA;
74 uint_fast16_t uiZ64;
75 uint64_t sigZ, lastBitMask, roundBitsMask;
76
77 /*------------------------------------------------------------------------
78 *------------------------------------------------------------------------*/
79 aSPtr = (const struct extFloat80M *) aPtr;
80 zSPtr = (struct extFloat80M *) zPtr;
81 /*------------------------------------------------------------------------
82 *------------------------------------------------------------------------*/
83 uiA64 = aSPtr->signExp;
84 signUI64 = uiA64 & packToExtF80UI64( 1, 0 );
85 exp = expExtF80UI64( uiA64 );
86 sigA = aSPtr->signif;
87 /*------------------------------------------------------------------------
88 *------------------------------------------------------------------------*/
89 if ( !(sigA & UINT64_C( 0x8000000000000000 )) && (exp != 0x7FFF) ) {
90 if ( !sigA ) {
91 uiZ64 = signUI64;
92 sigZ = 0;
93 goto uiZ;
94 }
95 exp += softfloat_normExtF80SigM( &sigA );
96 }
97 /*------------------------------------------------------------------------
98 *------------------------------------------------------------------------*/
99 if ( exp <= 0x3FFE ) {
100 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
101 switch ( roundingMode ) {
102 case softfloat_round_near_even:
103 if ( !(sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) break;
104 case softfloat_round_near_maxMag:
105 if ( exp == 0x3FFE ) goto mag1;
106 break;
107 case softfloat_round_min:
108 if ( signUI64 ) goto mag1;
109 break;
110 case softfloat_round_max:
111 if ( !signUI64 ) goto mag1;
112 break;
113#ifdef SOFTFLOAT_ROUND_ODD
114 case softfloat_round_odd:
115 goto mag1;
116#endif
117 }
118 uiZ64 = signUI64;
119 sigZ = 0;
120 goto uiZ;
121 mag1:
122 uiZ64 = signUI64 | 0x3FFF;
123 sigZ = UINT64_C( 0x8000000000000000 );
124 goto uiZ;
125 }
126 /*------------------------------------------------------------------------
127 *------------------------------------------------------------------------*/
128 if ( 0x403E <= exp ) {
129 if ( exp == 0x7FFF ) {
130 if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
131 softfloat_propagateNaNExtF80M( aSPtr, 0, zSPtr );
132 return;
133 }
134 sigZ = UINT64_C( 0x8000000000000000 );
135 } else {
136 sigZ = sigA;
137 }
138 uiZ64 = signUI64 | exp;
139 goto uiZ;
140 }
141 /*------------------------------------------------------------------------
142 *------------------------------------------------------------------------*/
143 uiZ64 = signUI64 | exp;
144 lastBitMask = (uint64_t) 1<<(0x403E - exp);
145 roundBitsMask = lastBitMask - 1;
146 sigZ = sigA;
147 if ( roundingMode == softfloat_round_near_maxMag ) {
148 sigZ += lastBitMask>>1;
149 } else if ( roundingMode == softfloat_round_near_even ) {
150 sigZ += lastBitMask>>1;
151 if ( !(sigZ & roundBitsMask) ) sigZ &= ~lastBitMask;
152 } else if (
153 roundingMode == (signUI64 ? softfloat_round_min : softfloat_round_max)
154 ) {
155 sigZ += roundBitsMask;
156 }
157 sigZ &= ~roundBitsMask;
158 if ( !sigZ ) {
159 ++uiZ64;
160 sigZ = UINT64_C( 0x8000000000000000 );
161 }
162 if ( sigZ != sigA ) {
163#ifdef SOFTFLOAT_ROUND_ODD
164 if ( roundingMode == softfloat_round_odd ) sigZ |= lastBitMask;
165#endif
166 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
167 }
168 uiZ:
169 zSPtr->signExp = uiZ64;
170 zSPtr->signif = sigZ;
171 return;
172
173}
174
175#endif
176
deps/SoftFloat-3e/source/extF80M_sqrt.c deleted-180
...@@ -1,180 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void extF80M_sqrt( const extFloat80_t *aPtr, extFloat80_t *zPtr )
47{
48
49 *zPtr = extF80_sqrt( *aPtr );
50
51}
52
53#else
54
55void extF80M_sqrt( const extFloat80_t *aPtr, extFloat80_t *zPtr )
56{
57 const struct extFloat80M *aSPtr;
58 struct extFloat80M *zSPtr;
59 uint_fast16_t uiA64, signUI64;
60 int32_t expA;
61 uint64_t rem64;
62 int32_t expZ;
63 uint32_t rem96[3], sig32A, recipSqrt32, sig32Z, q;
64 uint64_t sig64Z, x64;
65 uint32_t rem32, term[4], rem[4], extSigZ[3];
66
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 aSPtr = (const struct extFloat80M *) aPtr;
70 zSPtr = (struct extFloat80M *) zPtr;
71 /*------------------------------------------------------------------------
72 *------------------------------------------------------------------------*/
73 uiA64 = aSPtr->signExp;
74 signUI64 = uiA64 & packToExtF80UI64( 1, 0 );
75 expA = expExtF80UI64( uiA64 );
76 rem64 = aSPtr->signif;
77 /*------------------------------------------------------------------------
78 *------------------------------------------------------------------------*/
79 if ( expA == 0x7FFF ) {
80 if ( rem64 & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
81 softfloat_propagateNaNExtF80M( aSPtr, 0, zSPtr );
82 return;
83 }
84 if ( signUI64 ) goto invalid;
85 rem64 = UINT64_C( 0x8000000000000000 );
86 goto copyA;
87 }
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 if ( ! expA ) expA = 1;
91 if ( ! (rem64 & UINT64_C( 0x8000000000000000 )) ) {
92 if ( ! rem64 ) {
93 uiA64 = signUI64;
94 goto copyA;
95 }
96 expA += softfloat_normExtF80SigM( &rem64 );
97 }
98 if ( signUI64 ) goto invalid;
99 /*------------------------------------------------------------------------
100 *------------------------------------------------------------------------*/
101 expZ = ((expA - 0x3FFF)>>1) + 0x3FFF;
102 expA &= 1;
103 softfloat_shortShiftLeft64To96M( rem64, 30 - expA, rem96 );
104 sig32A = rem64>>32;
105 recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A );
106 sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32;
107 if ( expA ) sig32Z >>= 1;
108 rem64 =
109 ((uint64_t) rem96[indexWord( 3, 2 )]<<32 | rem96[indexWord( 3, 1 )])
110 - (uint64_t) sig32Z * sig32Z;
111 rem96[indexWord( 3, 2 )] = rem64>>32;
112 rem96[indexWord( 3, 1 )] = rem64;
113 /*------------------------------------------------------------------------
114 *------------------------------------------------------------------------*/
115 q = ((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32;
116 sig64Z = ((uint64_t) sig32Z<<32) + ((uint64_t) q<<3);
117 term[indexWord( 3, 2 )] = 0;
118 /*------------------------------------------------------------------------
119 | (Repeating this loop is a rare occurrence.)
120 *------------------------------------------------------------------------*/
121 for (;;) {
122 x64 = ((uint64_t) sig32Z<<32) + sig64Z;
123 term[indexWord( 3, 1 )] = x64>>32;
124 term[indexWord( 3, 0 )] = x64;
125 softfloat_remStep96MBy32(
126 rem96, 29, term, q, &rem[indexMultiwordHi( 4, 3 )] );
127 rem32 = rem[indexWord( 4, 3 )];
128 if ( ! (rem32 & 0x80000000) ) break;
129 --q;
130 sig64Z -= 1<<3;
131 }
132 rem64 = (uint64_t) rem32<<32 | rem[indexWord( 4, 2 )];
133 /*------------------------------------------------------------------------
134 *------------------------------------------------------------------------*/
135 q = (((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32) + 2;
136 if ( rem64>>34 ) q += recipSqrt32;
137 x64 = (uint64_t) q<<7;
138 extSigZ[indexWord( 3, 0 )] = x64;
139 x64 = (sig64Z<<1) + (x64>>32);
140 extSigZ[indexWord( 3, 2 )] = x64>>32;
141 extSigZ[indexWord( 3, 1 )] = x64;
142 /*------------------------------------------------------------------------
143 *------------------------------------------------------------------------*/
144 if ( (q & 0xFFFFFF) <= 2 ) {
145 q &= ~(uint32_t) 0xFFFF;
146 extSigZ[indexWordLo( 3 )] = q<<7;
147 x64 = sig64Z + (q>>27);
148 term[indexWord( 4, 3 )] = 0;
149 term[indexWord( 4, 2 )] = x64>>32;
150 term[indexWord( 4, 1 )] = x64;
151 term[indexWord( 4, 0 )] = q<<5;
152 rem[indexWord( 4, 0 )] = 0;
153 softfloat_remStep128MBy32( rem, 28, term, q, rem );
154 q = rem[indexWordHi( 4 )];
155 if ( q & 0x80000000 ) {
156 softfloat_sub1X96M( extSigZ );
157 } else {
158 if ( q || rem[indexWord( 4, 1 )] || rem[indexWord( 4, 2 )] ) {
159 extSigZ[indexWordLo( 3 )] |= 1;
160 }
161 }
162 }
163 softfloat_roundPackMToExtF80M(
164 0, expZ, extSigZ, extF80_roundingPrecision, zSPtr );
165 return;
166 /*------------------------------------------------------------------------
167 *------------------------------------------------------------------------*/
168 invalid:
169 softfloat_invalidExtF80M( zSPtr );
170 return;
171 /*------------------------------------------------------------------------
172 *------------------------------------------------------------------------*/
173 copyA:
174 zSPtr->signExp = uiA64;
175 zSPtr->signif = rem64;
176
177}
178
179#endif
180
deps/SoftFloat-3e/source/extF80M_sub.c deleted-100
...@@ -1,100 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42#ifdef SOFTFLOAT_FAST_INT64
43
44void
45 extF80M_sub(
46 const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
47{
48 const struct extFloat80M *aSPtr, *bSPtr;
49 uint_fast16_t uiA64;
50 uint_fast64_t uiA0;
51 bool signA;
52 uint_fast16_t uiB64;
53 uint_fast64_t uiB0;
54 bool signB;
55#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
56 extFloat80_t
57 (*magsFuncPtr)(
58 uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool );
59#endif
60
61 aSPtr = (const struct extFloat80M *) aPtr;
62 bSPtr = (const struct extFloat80M *) bPtr;
63 uiA64 = aSPtr->signExp;
64 uiA0 = aSPtr->signif;
65 signA = signExtF80UI64( uiA64 );
66 uiB64 = bSPtr->signExp;
67 uiB0 = bSPtr->signif;
68 signB = signExtF80UI64( uiB64 );
69#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
70 if ( signA == signB ) {
71 *zPtr = softfloat_subMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA );
72 } else {
73 *zPtr = softfloat_addMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA );
74 }
75#else
76 magsFuncPtr =
77 (signA == signB) ? softfloat_subMagsExtF80 : softfloat_addMagsExtF80;
78 *zPtr = (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
79#endif
80
81}
82
83#else
84
85void
86 extF80M_sub(
87 const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
88{
89
90 softfloat_addExtF80M(
91 (const struct extFloat80M *) aPtr,
92 (const struct extFloat80M *) bPtr,
93 (struct extFloat80M *) zPtr,
94 true
95 );
96
97}
98
99#endif
100
deps/SoftFloat-3e/source/extF80M_to_f128M.c deleted-125
...@@ -1,125 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *zPtr )
47{
48
49 *zPtr = extF80_to_f128( *aPtr );
50
51}
52
53#else
54
55void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *zPtr )
56{
57 const struct extFloat80M *aSPtr;
58 uint32_t *zWPtr;
59 uint_fast16_t uiA64;
60 bool sign;
61 int32_t exp;
62 uint64_t sig;
63 struct commonNaN commonNaN;
64 uint32_t uiZ96;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 aSPtr = (const struct extFloat80M *) aPtr;
69 zWPtr = (uint32_t *) zPtr;
70 /*------------------------------------------------------------------------
71 *------------------------------------------------------------------------*/
72 uiA64 = aSPtr->signExp;
73 sign = signExtF80UI64( uiA64 );
74 exp = expExtF80UI64( uiA64 );
75 sig = aSPtr->signif;
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 zWPtr[indexWord( 4, 0 )] = 0;
79 if ( exp == 0x7FFF ) {
80 if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
81 softfloat_extF80MToCommonNaN( aSPtr, &commonNaN );
82 softfloat_commonNaNToF128M( &commonNaN, zWPtr );
83 return;
84 }
85 uiZ96 = packToF128UI96( sign, 0x7FFF, 0 );
86 goto uiZ;
87 }
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 if ( exp ) --exp;
91 if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) {
92 if ( ! sig ) {
93 uiZ96 = packToF128UI96( sign, 0, 0 );
94 goto uiZ;
95 }
96 exp += softfloat_normExtF80SigM( &sig );
97 }
98 /*------------------------------------------------------------------------
99 *------------------------------------------------------------------------*/
100 zWPtr[indexWord( 4, 1 )] = (uint32_t) sig<<17;
101 sig >>= 15;
102 zWPtr[indexWord( 4, 2 )] = sig;
103 if ( exp < 0 ) {
104 zWPtr[indexWordHi( 4 )] = sig>>32;
105 softfloat_shiftRight96M(
106 &zWPtr[indexMultiwordHi( 4, 3 )],
107 -exp,
108 &zWPtr[indexMultiwordHi( 4, 3 )]
109 );
110 exp = 0;
111 sig = (uint64_t) zWPtr[indexWordHi( 4 )]<<32;
112 }
113 zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, exp, sig>>32 );
114 return;
115 /*------------------------------------------------------------------------
116 *------------------------------------------------------------------------*/
117 uiZ:
118 zWPtr[indexWord( 4, 3 )] = uiZ96;
119 zWPtr[indexWord( 4, 2 )] = 0;
120 zWPtr[indexWord( 4, 1 )] = 0;
121
122}
123
124#endif
125
deps/SoftFloat-3e/source/extF80M_to_f16.c deleted-112
...@@ -1,112 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46float16_t extF80M_to_f16( const extFloat80_t *aPtr )
47{
48
49 return extF80_to_f16( *aPtr );
50
51}
52
53#else
54
55float16_t extF80M_to_f16( const extFloat80_t *aPtr )
56{
57 const struct extFloat80M *aSPtr;
58 uint_fast16_t uiA64;
59 bool sign;
60 int32_t exp;
61 uint64_t sig;
62 struct commonNaN commonNaN;
63 uint16_t uiZ, sig16;
64 union ui16_f16 uZ;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 aSPtr = (const struct extFloat80M *) aPtr;
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 uiA64 = aSPtr->signExp;
72 sign = signExtF80UI64( uiA64 );
73 exp = expExtF80UI64( uiA64 );
74 sig = aSPtr->signif;
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 if ( exp == 0x7FFF ) {
78 if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
79 softfloat_extF80MToCommonNaN( aSPtr, &commonNaN );
80 uiZ = softfloat_commonNaNToF16UI( &commonNaN );
81 } else {
82 uiZ = packToF16UI( sign, 0x1F, 0 );
83 }
84 goto uiZ;
85 }
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) {
89 if ( ! sig ) {
90 uiZ = packToF16UI( sign, 0, 0 );
91 goto uiZ;
92 }
93 exp += softfloat_normExtF80SigM( &sig );
94 }
95 /*------------------------------------------------------------------------
96 *------------------------------------------------------------------------*/
97 sig16 = softfloat_shortShiftRightJam64( sig, 49 );
98 exp -= 0x3FF1;
99 if ( sizeof (int_fast16_t) < sizeof (int32_t) ) {
100 if ( exp < -0x40 ) exp = -0x40;
101 }
102 return softfloat_roundPackToF16( sign, exp, sig16 );
103 /*------------------------------------------------------------------------
104 *------------------------------------------------------------------------*/
105 uiZ:
106 uZ.ui = uiZ;
107 return uZ.f;
108
109}
110
111#endif
112
deps/SoftFloat-3e/source/extF80M_to_f32.c deleted-112
...@@ -1,112 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46float32_t extF80M_to_f32( const extFloat80_t *aPtr )
47{
48
49 return extF80_to_f32( *aPtr );
50
51}
52
53#else
54
55float32_t extF80M_to_f32( const extFloat80_t *aPtr )
56{
57 const struct extFloat80M *aSPtr;
58 uint_fast16_t uiA64;
59 bool sign;
60 int32_t exp;
61 uint64_t sig;
62 struct commonNaN commonNaN;
63 uint32_t uiZ, sig32;
64 union ui32_f32 uZ;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 aSPtr = (const struct extFloat80M *) aPtr;
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 uiA64 = aSPtr->signExp;
72 sign = signExtF80UI64( uiA64 );
73 exp = expExtF80UI64( uiA64 );
74 sig = aSPtr->signif;
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 if ( exp == 0x7FFF ) {
78 if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
79 softfloat_extF80MToCommonNaN( aSPtr, &commonNaN );
80 uiZ = softfloat_commonNaNToF32UI( &commonNaN );
81 } else {
82 uiZ = packToF32UI( sign, 0xFF, 0 );
83 }
84 goto uiZ;
85 }
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) {
89 if ( ! sig ) {
90 uiZ = packToF32UI( sign, 0, 0 );
91 goto uiZ;
92 }
93 exp += softfloat_normExtF80SigM( &sig );
94 }
95 /*------------------------------------------------------------------------
96 *------------------------------------------------------------------------*/
97 sig32 = softfloat_shortShiftRightJam64( sig, 33 );
98 exp -= 0x3F81;
99 if ( sizeof (int_fast16_t) < sizeof (int32_t) ) {
100 if ( exp < -0x1000 ) exp = -0x1000;
101 }
102 return softfloat_roundPackToF32( sign, exp, sig32 );
103 /*------------------------------------------------------------------------
104 *------------------------------------------------------------------------*/
105 uiZ:
106 uZ.ui = uiZ;
107 return uZ.f;
108
109}
110
111#endif
112
deps/SoftFloat-3e/source/extF80M_to_f64.c deleted-112
...@@ -1,112 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46float64_t extF80M_to_f64( const extFloat80_t *aPtr )
47{
48
49 return extF80_to_f64( *aPtr );
50
51}
52
53#else
54
55float64_t extF80M_to_f64( const extFloat80_t *aPtr )
56{
57 const struct extFloat80M *aSPtr;
58 uint_fast16_t uiA64;
59 bool sign;
60 int32_t exp;
61 uint64_t sig;
62 struct commonNaN commonNaN;
63 uint64_t uiZ;
64 union ui64_f64 uZ;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 aSPtr = (const struct extFloat80M *) aPtr;
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 uiA64 = aSPtr->signExp;
72 sign = signExtF80UI64( uiA64 );
73 exp = expExtF80UI64( uiA64 );
74 sig = aSPtr->signif;
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 if ( exp == 0x7FFF ) {
78 if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
79 softfloat_extF80MToCommonNaN( aSPtr, &commonNaN );
80 uiZ = softfloat_commonNaNToF64UI( &commonNaN );
81 } else {
82 uiZ = packToF64UI( sign, 0x7FF, 0 );
83 }
84 goto uiZ;
85 }
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) {
89 if ( ! sig ) {
90 uiZ = packToF64UI( sign, 0, 0 );
91 goto uiZ;
92 }
93 exp += softfloat_normExtF80SigM( &sig );
94 }
95 /*------------------------------------------------------------------------
96 *------------------------------------------------------------------------*/
97 sig = softfloat_shortShiftRightJam64( sig, 1 );
98 exp -= 0x3C01;
99 if ( sizeof (int_fast16_t) < sizeof (int32_t) ) {
100 if ( exp < -0x1000 ) exp = -0x1000;
101 }
102 return softfloat_roundPackToF64( sign, exp, sig );
103 /*------------------------------------------------------------------------
104 *------------------------------------------------------------------------*/
105 uiZ:
106 uZ.ui = uiZ;
107 return uZ.f;
108
109}
110
111#endif
112
deps/SoftFloat-3e/source/extF80M_to_i32.c deleted-100
...@@ -1,100 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46int_fast32_t
47 extF80M_to_i32(
48 const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact )
49{
50
51 return extF80_to_i32( *aPtr, roundingMode, exact );
52
53}
54
55#else
56
57int_fast32_t
58 extF80M_to_i32(
59 const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact )
60{
61 const struct extFloat80M *aSPtr;
62 uint_fast16_t uiA64;
63 bool sign;
64 int32_t exp;
65 uint64_t sig;
66 int32_t shiftDist;
67
68 /*------------------------------------------------------------------------
69 *------------------------------------------------------------------------*/
70 aSPtr = (const struct extFloat80M *) aPtr;
71 uiA64 = aSPtr->signExp;
72 sign = signExtF80UI64( uiA64 );
73 exp = expExtF80UI64( uiA64 );
74 sig = aSPtr->signif;
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 shiftDist = 0x4032 - exp;
78 if ( shiftDist <= 0 ) {
79 if ( sig>>32 ) goto invalid;
80 if ( -32 < shiftDist ) {
81 sig <<= -shiftDist;
82 } else {
83 if ( (uint32_t) sig ) goto invalid;
84 }
85 } else {
86 sig = softfloat_shiftRightJam64( sig, shiftDist );
87 }
88 return softfloat_roundToI32( sign, sig, roundingMode, exact );
89 /*------------------------------------------------------------------------
90 *------------------------------------------------------------------------*/
91 invalid:
92 softfloat_raiseFlags( softfloat_flag_invalid );
93 return
94 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ? i32_fromNaN
95 : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
96
97}
98
99#endif
100
deps/SoftFloat-3e/source/extF80M_to_i32_r_minMag.c deleted-120
...@@ -1,120 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *aPtr, bool exact )
47{
48
49 return extF80_to_i32_r_minMag( *aPtr, exact );
50
51}
52
53#else
54
55int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *aPtr, bool exact )
56{
57 const struct extFloat80M *aSPtr;
58 uint_fast16_t uiA64;
59 int32_t exp;
60 uint64_t sig;
61 int32_t shiftDist;
62 bool sign, raiseInexact;
63 int32_t z;
64 uint64_t shiftedSig;
65 uint32_t absZ;
66 union { uint32_t ui; int32_t i; } u;
67
68 /*------------------------------------------------------------------------
69 *------------------------------------------------------------------------*/
70 aSPtr = (const struct extFloat80M *) aPtr;
71 uiA64 = aSPtr->signExp;
72 exp = expExtF80UI64( uiA64 );
73 sig = aSPtr->signif;
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( ! sig && (exp != 0x7FFF) ) return 0;
77 shiftDist = 0x403E - exp;
78 if ( 64 <= shiftDist ) {
79 raiseInexact = exact;
80 z = 0;
81 } else {
82 sign = signExtF80UI64( uiA64 );
83 raiseInexact = false;
84 if ( shiftDist < 0 ) {
85 if ( sig>>32 || (shiftDist <= -31) ) goto invalid;
86 shiftedSig = (uint64_t) (uint32_t) sig<<-shiftDist;
87 if ( shiftedSig>>32 ) goto invalid;
88 absZ = shiftedSig;
89 } else {
90 shiftedSig = sig;
91 if ( shiftDist ) shiftedSig >>= shiftDist;
92 if ( shiftedSig>>32 ) goto invalid;
93 absZ = shiftedSig;
94 if ( exact && shiftDist ) {
95 raiseInexact = ((uint64_t) absZ<<shiftDist != sig);
96 }
97 }
98 if ( sign ) {
99 if ( 0x80000000 < absZ ) goto invalid;
100 u.ui = -absZ;
101 z = u.i;
102 } else {
103 if ( 0x80000000 <= absZ ) goto invalid;
104 z = absZ;
105 }
106 }
107 if ( raiseInexact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
108 return z;
109 /*------------------------------------------------------------------------
110 *------------------------------------------------------------------------*/
111 invalid:
112 softfloat_raiseFlags( softfloat_flag_invalid );
113 return
114 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ? i32_fromNaN
115 : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
116
117}
118
119#endif
120
deps/SoftFloat-3e/source/extF80M_to_i64.c deleted-97
...@@ -1,97 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46int_fast64_t
47 extF80M_to_i64(
48 const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact )
49{
50
51 return extF80_to_i64( *aPtr, roundingMode, exact );
52
53}
54
55#else
56
57int_fast64_t
58 extF80M_to_i64(
59 const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact )
60{
61 const struct extFloat80M *aSPtr;
62 uint_fast16_t uiA64;
63 bool sign;
64 int32_t exp;
65 uint64_t sig;
66 int32_t shiftDist;
67 uint32_t extSig[3];
68
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 aSPtr = (const struct extFloat80M *) aPtr;
72 uiA64 = aSPtr->signExp;
73 sign = signExtF80UI64( uiA64 );
74 exp = expExtF80UI64( uiA64 );
75 sig = aSPtr->signif;
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 shiftDist = 0x403E - exp;
79 if ( shiftDist < 0 ) {
80 softfloat_raiseFlags( softfloat_flag_invalid );
81 return
82 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
83 ? i64_fromNaN
84 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
85 }
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 extSig[indexWord( 3, 2 )] = sig>>32;
89 extSig[indexWord( 3, 1 )] = sig;
90 extSig[indexWord( 3, 0 )] = 0;
91 if ( shiftDist ) softfloat_shiftRightJam96M( extSig, shiftDist, extSig );
92 return softfloat_roundMToI64( sign, extSig, roundingMode, exact );
93
94}
95
96#endif
97
deps/SoftFloat-3e/source/extF80M_to_i64_r_minMag.c deleted-115
...@@ -1,115 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *aPtr, bool exact )
47{
48
49 return extF80_to_i64_r_minMag( *aPtr, exact );
50
51}
52
53#else
54
55int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *aPtr, bool exact )
56{
57 const struct extFloat80M *aSPtr;
58 uint_fast16_t uiA64;
59 int32_t exp;
60 uint64_t sig;
61 int32_t shiftDist;
62 bool sign, raiseInexact;
63 int64_t z;
64 uint64_t absZ;
65 union { uint64_t ui; int64_t i; } u;
66
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 aSPtr = (const struct extFloat80M *) aPtr;
70 uiA64 = aSPtr->signExp;
71 exp = expExtF80UI64( uiA64 );
72 sig = aSPtr->signif;
73 /*------------------------------------------------------------------------
74 *------------------------------------------------------------------------*/
75 if ( ! sig && (exp != 0x7FFF) ) return 0;
76 shiftDist = 0x403E - exp;
77 if ( 64 <= shiftDist ) {
78 raiseInexact = exact;
79 z = 0;
80 } else {
81 sign = signExtF80UI64( uiA64 );
82 raiseInexact = false;
83 if ( shiftDist < 0 ) {
84 if ( shiftDist <= -63 ) goto invalid;
85 shiftDist = -shiftDist;
86 absZ = sig<<shiftDist;
87 if ( absZ>>shiftDist != sig ) goto invalid;
88 } else {
89 absZ = sig;
90 if ( shiftDist ) absZ >>= shiftDist;
91 if ( exact && shiftDist ) raiseInexact = (absZ<<shiftDist != sig);
92 }
93 if ( sign ) {
94 if ( UINT64_C( 0x8000000000000000 ) < absZ ) goto invalid;
95 u.ui = -absZ;
96 z = u.i;
97 } else {
98 if ( UINT64_C( 0x8000000000000000 ) <= absZ ) goto invalid;
99 z = absZ;
100 }
101 }
102 if ( raiseInexact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
103 return z;
104 /*------------------------------------------------------------------------
105 *------------------------------------------------------------------------*/
106 invalid:
107 softfloat_raiseFlags( softfloat_flag_invalid );
108 return
109 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ? i64_fromNaN
110 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
111
112}
113
114#endif
115
deps/SoftFloat-3e/source/extF80M_to_ui32.c deleted-101
...@@ -1,101 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46uint_fast32_t
47 extF80M_to_ui32(
48 const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact )
49{
50
51 return extF80_to_ui32( *aPtr, roundingMode, exact );
52
53}
54
55#else
56
57uint_fast32_t
58 extF80M_to_ui32(
59 const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact )
60{
61 const struct extFloat80M *aSPtr;
62 uint_fast16_t uiA64;
63 bool sign;
64 int32_t exp;
65 uint64_t sig;
66 int32_t shiftDist;
67
68 /*------------------------------------------------------------------------
69 *------------------------------------------------------------------------*/
70 aSPtr = (const struct extFloat80M *) aPtr;
71 uiA64 = aSPtr->signExp;
72 sign = signExtF80UI64( uiA64 );
73 exp = expExtF80UI64( uiA64 );
74 sig = aSPtr->signif;
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 shiftDist = 0x4032 - exp;
78 if ( shiftDist <= 0 ) {
79 if ( sig>>32 ) goto invalid;
80 if ( -32 < shiftDist ) {
81 sig <<= -shiftDist;
82 } else {
83 if ( (uint32_t) sig ) goto invalid;
84 }
85 } else {
86 sig = softfloat_shiftRightJam64( sig, shiftDist );
87 }
88 return softfloat_roundToUI32( sign, sig, roundingMode, exact );
89 /*------------------------------------------------------------------------
90 *------------------------------------------------------------------------*/
91 invalid:
92 softfloat_raiseFlags( softfloat_flag_invalid );
93 return
94 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
95 ? ui32_fromNaN
96 : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
97
98}
99
100#endif
101
deps/SoftFloat-3e/source/extF80M_to_ui32_r_minMag.c deleted-111
...@@ -1,111 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *aPtr, bool exact )
47{
48
49 return extF80_to_ui32_r_minMag( *aPtr, exact );
50
51}
52
53#else
54
55uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *aPtr, bool exact )
56{
57 const struct extFloat80M *aSPtr;
58 uint_fast16_t uiA64;
59 int32_t exp;
60 uint64_t sig;
61 int32_t shiftDist;
62 bool sign;
63 uint64_t shiftedSig;
64 uint32_t z;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 aSPtr = (const struct extFloat80M *) aPtr;
69 uiA64 = aSPtr->signExp;
70 exp = expExtF80UI64( uiA64 );
71 sig = aSPtr->signif;
72 /*------------------------------------------------------------------------
73 *------------------------------------------------------------------------*/
74 if ( ! sig && (exp != 0x7FFF) ) return 0;
75 shiftDist = 0x403E - exp;
76 if ( 64 <= shiftDist ) {
77 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
78 return 0;
79 }
80 /*------------------------------------------------------------------------
81 *------------------------------------------------------------------------*/
82 sign = signExtF80UI64( uiA64 );
83 if ( shiftDist < 0 ) {
84 if ( sign || sig>>32 || (shiftDist <= -31) ) goto invalid;
85 shiftedSig = (uint64_t) (uint32_t) sig<<-shiftDist;
86 if ( shiftedSig>>32 ) goto invalid;
87 z = shiftedSig;
88 } else {
89 shiftedSig = sig;
90 if ( shiftDist ) shiftedSig >>= shiftDist;
91 if ( shiftedSig>>32 ) goto invalid;
92 z = shiftedSig;
93 if ( sign && z ) goto invalid;
94 if ( exact && shiftDist && ((uint64_t) z<<shiftDist != sig) ) {
95 softfloat_exceptionFlags |= softfloat_flag_inexact;
96 }
97 }
98 return z;
99 /*------------------------------------------------------------------------
100 *------------------------------------------------------------------------*/
101 invalid:
102 softfloat_raiseFlags( softfloat_flag_invalid );
103 return
104 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
105 ? ui32_fromNaN
106 : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
107
108}
109
110#endif
111
deps/SoftFloat-3e/source/extF80M_to_ui64.c deleted-97
...@@ -1,97 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46uint_fast64_t
47 extF80M_to_ui64(
48 const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact )
49{
50
51 return extF80_to_ui64( *aPtr, roundingMode, exact );
52
53}
54
55#else
56
57uint_fast64_t
58 extF80M_to_ui64(
59 const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact )
60{
61 const struct extFloat80M *aSPtr;
62 uint_fast16_t uiA64;
63 bool sign;
64 int32_t exp;
65 uint64_t sig;
66 int32_t shiftDist;
67 uint32_t extSig[3];
68
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 aSPtr = (const struct extFloat80M *) aPtr;
72 uiA64 = aSPtr->signExp;
73 sign = signExtF80UI64( uiA64 );
74 exp = expExtF80UI64( uiA64 );
75 sig = aSPtr->signif;
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 shiftDist = 0x403E - exp;
79 if ( shiftDist < 0 ) {
80 softfloat_raiseFlags( softfloat_flag_invalid );
81 return
82 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
83 ? ui64_fromNaN
84 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
85 }
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 extSig[indexWord( 3, 2 )] = sig>>32;
89 extSig[indexWord( 3, 1 )] = sig;
90 extSig[indexWord( 3, 0 )] = 0;
91 if ( shiftDist ) softfloat_shiftRightJam96M( extSig, shiftDist, extSig );
92 return softfloat_roundMToUI64( sign, extSig, roundingMode, exact );
93
94}
95
96#endif
97
deps/SoftFloat-3e/source/extF80M_to_ui64_r_minMag.c deleted-108
...@@ -1,108 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *aPtr, bool exact )
47{
48
49 return extF80_to_ui64_r_minMag( *aPtr, exact );
50
51}
52
53#else
54
55uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *aPtr, bool exact )
56{
57 const struct extFloat80M *aSPtr;
58 uint_fast16_t uiA64;
59 int32_t exp;
60 uint64_t sig;
61 int32_t shiftDist;
62 bool sign;
63 uint64_t z;
64
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 aSPtr = (const struct extFloat80M *) aPtr;
68 uiA64 = aSPtr->signExp;
69 exp = expExtF80UI64( uiA64 );
70 sig = aSPtr->signif;
71 /*------------------------------------------------------------------------
72 *------------------------------------------------------------------------*/
73 if ( ! sig && (exp != 0x7FFF) ) return 0;
74 shiftDist = 0x403E - exp;
75 if ( 64 <= shiftDist ) {
76 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
77 return 0;
78 }
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 sign = signExtF80UI64( uiA64 );
82 if ( shiftDist < 0 ) {
83 if ( sign || (shiftDist <= -63) ) goto invalid;
84 shiftDist = -shiftDist;
85 z = sig<<shiftDist;
86 if ( z>>shiftDist != sig ) goto invalid;
87 } else {
88 z = sig;
89 if ( shiftDist ) z >>= shiftDist;
90 if ( sign && z ) goto invalid;
91 if ( exact && shiftDist && (z<<shiftDist != sig) ) {
92 softfloat_exceptionFlags |= softfloat_flag_inexact;
93 }
94 }
95 return z;
96 /*------------------------------------------------------------------------
97 *------------------------------------------------------------------------*/
98 invalid:
99 softfloat_raiseFlags( softfloat_flag_invalid );
100 return
101 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
102 ? ui64_fromNaN
103 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
104
105}
106
107#endif
108
deps/SoftFloat-3e/source/extF80_add.c deleted-80
...@@ -1,80 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43extFloat80_t extF80_add( extFloat80_t a, extFloat80_t b )
44{
45 union { struct extFloat80M s; extFloat80_t f; } uA;
46 uint_fast16_t uiA64;
47 uint_fast64_t uiA0;
48 bool signA;
49 union { struct extFloat80M s; extFloat80_t f; } uB;
50 uint_fast16_t uiB64;
51 uint_fast64_t uiB0;
52 bool signB;
53#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
54 extFloat80_t
55 (*magsFuncPtr)(
56 uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool );
57#endif
58
59 uA.f = a;
60 uiA64 = uA.s.signExp;
61 uiA0 = uA.s.signif;
62 signA = signExtF80UI64( uiA64 );
63 uB.f = b;
64 uiB64 = uB.s.signExp;
65 uiB0 = uB.s.signif;
66 signB = signExtF80UI64( uiB64 );
67#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
68 if ( signA == signB ) {
69 return softfloat_addMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA );
70 } else {
71 return softfloat_subMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA );
72 }
73#else
74 magsFuncPtr =
75 (signA == signB) ? softfloat_addMagsExtF80 : softfloat_subMagsExtF80;
76 return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
77#endif
78
79}
80
deps/SoftFloat-3e/source/extF80_div.c deleted-203
...@@ -1,203 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44extFloat80_t extF80_div( extFloat80_t a, extFloat80_t b )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 bool signA;
50 int_fast32_t expA;
51 uint_fast64_t sigA;
52 union { struct extFloat80M s; extFloat80_t f; } uB;
53 uint_fast16_t uiB64;
54 uint_fast64_t uiB0;
55 bool signB;
56 int_fast32_t expB;
57 uint_fast64_t sigB;
58 bool signZ;
59 struct exp32_sig64 normExpSig;
60 int_fast32_t expZ;
61 struct uint128 rem;
62 uint_fast32_t recip32;
63 uint_fast64_t sigZ;
64 int ix;
65 uint_fast64_t q64;
66 uint_fast32_t q;
67 struct uint128 term;
68 uint_fast64_t sigZExtra;
69 struct uint128 uiZ;
70 uint_fast16_t uiZ64;
71 uint_fast64_t uiZ0;
72 union { struct extFloat80M s; extFloat80_t f; } uZ;
73
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 uA.f = a;
77 uiA64 = uA.s.signExp;
78 uiA0 = uA.s.signif;
79 signA = signExtF80UI64( uiA64 );
80 expA = expExtF80UI64( uiA64 );
81 sigA = uiA0;
82 uB.f = b;
83 uiB64 = uB.s.signExp;
84 uiB0 = uB.s.signif;
85 signB = signExtF80UI64( uiB64 );
86 expB = expExtF80UI64( uiB64 );
87 sigB = uiB0;
88 signZ = signA ^ signB;
89 /*------------------------------------------------------------------------
90 *------------------------------------------------------------------------*/
91 if ( expA == 0x7FFF ) {
92 if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN;
93 if ( expB == 0x7FFF ) {
94 if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN;
95 goto invalid;
96 }
97 goto infinity;
98 }
99 if ( expB == 0x7FFF ) {
100 if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN;
101 goto zero;
102 }
103 /*------------------------------------------------------------------------
104 *------------------------------------------------------------------------*/
105 if ( ! expB ) expB = 1;
106 if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) {
107 if ( ! sigB ) {
108 if ( ! sigA ) goto invalid;
109 softfloat_raiseFlags( softfloat_flag_infinite );
110 goto infinity;
111 }
112 normExpSig = softfloat_normSubnormalExtF80Sig( sigB );
113 expB += normExpSig.exp;
114 sigB = normExpSig.sig;
115 }
116 if ( ! expA ) expA = 1;
117 if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) {
118 if ( ! sigA ) goto zero;
119 normExpSig = softfloat_normSubnormalExtF80Sig( sigA );
120 expA += normExpSig.exp;
121 sigA = normExpSig.sig;
122 }
123 /*------------------------------------------------------------------------
124 *------------------------------------------------------------------------*/
125 expZ = expA - expB + 0x3FFF;
126 if ( sigA < sigB ) {
127 --expZ;
128 rem = softfloat_shortShiftLeft128( 0, sigA, 32 );
129 } else {
130 rem = softfloat_shortShiftLeft128( 0, sigA, 31 );
131 }
132 recip32 = softfloat_approxRecip32_1( sigB>>32 );
133 sigZ = 0;
134 ix = 2;
135 for (;;) {
136 q64 = (uint_fast64_t) (uint32_t) (rem.v64>>2) * recip32;
137 q = (q64 + 0x80000000)>>32;
138 --ix;
139 if ( ix < 0 ) break;
140 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
141 term = softfloat_mul64ByShifted32To128( sigB, q );
142 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
143 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
144 --q;
145 rem = softfloat_add128( rem.v64, rem.v0, sigB>>32, sigB<<32 );
146 }
147 sigZ = (sigZ<<29) + q;
148 }
149 /*------------------------------------------------------------------------
150 *------------------------------------------------------------------------*/
151 if ( ((q + 1) & 0x3FFFFF) < 2 ) {
152 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
153 term = softfloat_mul64ByShifted32To128( sigB, q );
154 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
155 term = softfloat_shortShiftLeft128( 0, sigB, 32 );
156 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
157 --q;
158 rem = softfloat_add128( rem.v64, rem.v0, term.v64, term.v0 );
159 } else if ( softfloat_le128( term.v64, term.v0, rem.v64, rem.v0 ) ) {
160 ++q;
161 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
162 }
163 if ( rem.v64 | rem.v0 ) q |= 1;
164 }
165 /*------------------------------------------------------------------------
166 *------------------------------------------------------------------------*/
167 sigZ = (sigZ<<6) + (q>>23);
168 sigZExtra = (uint64_t) ((uint_fast64_t) q<<41);
169 return
170 softfloat_roundPackToExtF80(
171 signZ, expZ, sigZ, sigZExtra, extF80_roundingPrecision );
172 /*------------------------------------------------------------------------
173 *------------------------------------------------------------------------*/
174 propagateNaN:
175 uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 );
176 uiZ64 = uiZ.v64;
177 uiZ0 = uiZ.v0;
178 goto uiZ;
179 /*------------------------------------------------------------------------
180 *------------------------------------------------------------------------*/
181 invalid:
182 softfloat_raiseFlags( softfloat_flag_invalid );
183 uiZ64 = defaultNaNExtF80UI64;
184 uiZ0 = defaultNaNExtF80UI0;
185 goto uiZ;
186 /*------------------------------------------------------------------------
187 *------------------------------------------------------------------------*/
188 infinity:
189 uiZ64 = packToExtF80UI64( signZ, 0x7FFF );
190 uiZ0 = UINT64_C( 0x8000000000000000 );
191 goto uiZ;
192 /*------------------------------------------------------------------------
193 *------------------------------------------------------------------------*/
194 zero:
195 uiZ64 = packToExtF80UI64( signZ, 0 );
196 uiZ0 = 0;
197 uiZ:
198 uZ.s.signExp = uiZ64;
199 uZ.s.signif = uiZ0;
200 return uZ.f;
201
202}
203
deps/SoftFloat-3e/source/extF80_eq.c deleted-73
...@@ -1,73 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool extF80_eq( extFloat80_t a, extFloat80_t b )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 union { struct extFloat80M s; extFloat80_t f; } uB;
50 uint_fast16_t uiB64;
51 uint_fast64_t uiB0;
52
53 uA.f = a;
54 uiA64 = uA.s.signExp;
55 uiA0 = uA.s.signif;
56 uB.f = b;
57 uiB64 = uB.s.signExp;
58 uiB0 = uB.s.signif;
59 if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
60 if (
61 softfloat_isSigNaNExtF80UI( uiA64, uiA0 )
62 || softfloat_isSigNaNExtF80UI( uiB64, uiB0 )
63 ) {
64 softfloat_raiseFlags( softfloat_flag_invalid );
65 }
66 return false;
67 }
68 return
69 (uiA0 == uiB0)
70 && ((uiA64 == uiB64) || (! uiA0 && ! ((uiA64 | uiB64) & 0x7FFF)));
71
72}
73
deps/SoftFloat-3e/source/extF80_eq_signaling.c deleted-67
...@@ -1,67 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43bool extF80_eq_signaling( extFloat80_t a, extFloat80_t b )
44{
45 union { struct extFloat80M s; extFloat80_t f; } uA;
46 uint_fast16_t uiA64;
47 uint_fast64_t uiA0;
48 union { struct extFloat80M s; extFloat80_t f; } uB;
49 uint_fast16_t uiB64;
50 uint_fast64_t uiB0;
51
52 uA.f = a;
53 uiA64 = uA.s.signExp;
54 uiA0 = uA.s.signif;
55 uB.f = b;
56 uiB64 = uB.s.signExp;
57 uiB0 = uB.s.signif;
58 if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
59 softfloat_raiseFlags( softfloat_flag_invalid );
60 return false;
61 }
62 return
63 (uiA0 == uiB0)
64 && ((uiA64 == uiB64) || (! uiA0 && ! ((uiA64 | uiB64) & 0x7FFF)));
65
66}
67
deps/SoftFloat-3e/source/extF80_isSignalingNaN.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include "platform.h"
39#include "internals.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43bool extF80_isSignalingNaN( extFloat80_t a )
44{
45 union { struct extFloat80M s; extFloat80_t f; } uA;
46
47 uA.f = a;
48 return softfloat_isSigNaNExtF80UI( uA.s.signExp, uA.s.signif );
49
50}
51
deps/SoftFloat-3e/source/extF80_le.c deleted-73
...@@ -1,73 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool extF80_le( extFloat80_t a, extFloat80_t b )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 union { struct extFloat80M s; extFloat80_t f; } uB;
50 uint_fast16_t uiB64;
51 uint_fast64_t uiB0;
52 bool signA, signB;
53
54 uA.f = a;
55 uiA64 = uA.s.signExp;
56 uiA0 = uA.s.signif;
57 uB.f = b;
58 uiB64 = uB.s.signExp;
59 uiB0 = uB.s.signif;
60 if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
61 softfloat_raiseFlags( softfloat_flag_invalid );
62 return false;
63 }
64 signA = signExtF80UI64( uiA64 );
65 signB = signExtF80UI64( uiB64 );
66 return
67 (signA != signB)
68 ? signA || ! (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0)
69 : ((uiA64 == uiB64) && (uiA0 == uiB0))
70 || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
71
72}
73
deps/SoftFloat-3e/source/extF80_le_quiet.c deleted-78
...@@ -1,78 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool extF80_le_quiet( extFloat80_t a, extFloat80_t b )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 union { struct extFloat80M s; extFloat80_t f; } uB;
50 uint_fast16_t uiB64;
51 uint_fast64_t uiB0;
52 bool signA, signB;
53
54 uA.f = a;
55 uiA64 = uA.s.signExp;
56 uiA0 = uA.s.signif;
57 uB.f = b;
58 uiB64 = uB.s.signExp;
59 uiB0 = uB.s.signif;
60 if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
61 if (
62 softfloat_isSigNaNExtF80UI( uiA64, uiA0 )
63 || softfloat_isSigNaNExtF80UI( uiB64, uiB0 )
64 ) {
65 softfloat_raiseFlags( softfloat_flag_invalid );
66 }
67 return false;
68 }
69 signA = signExtF80UI64( uiA64 );
70 signB = signExtF80UI64( uiB64 );
71 return
72 (signA != signB)
73 ? signA || ! (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0)
74 : ((uiA64 == uiB64) && (uiA0 == uiB0))
75 || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
76
77}
78
deps/SoftFloat-3e/source/extF80_lt.c deleted-73
...@@ -1,73 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool extF80_lt( extFloat80_t a, extFloat80_t b )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 union { struct extFloat80M s; extFloat80_t f; } uB;
50 uint_fast16_t uiB64;
51 uint_fast64_t uiB0;
52 bool signA, signB;
53
54 uA.f = a;
55 uiA64 = uA.s.signExp;
56 uiA0 = uA.s.signif;
57 uB.f = b;
58 uiB64 = uB.s.signExp;
59 uiB0 = uB.s.signif;
60 if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
61 softfloat_raiseFlags( softfloat_flag_invalid );
62 return false;
63 }
64 signA = signExtF80UI64( uiA64 );
65 signB = signExtF80UI64( uiB64 );
66 return
67 (signA != signB)
68 ? signA && (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0)
69 : ((uiA64 != uiB64) || (uiA0 != uiB0))
70 && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
71
72}
73
deps/SoftFloat-3e/source/extF80_lt_quiet.c deleted-78
...@@ -1,78 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool extF80_lt_quiet( extFloat80_t a, extFloat80_t b )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 union { struct extFloat80M s; extFloat80_t f; } uB;
50 uint_fast16_t uiB64;
51 uint_fast64_t uiB0;
52 bool signA, signB;
53
54 uA.f = a;
55 uiA64 = uA.s.signExp;
56 uiA0 = uA.s.signif;
57 uB.f = b;
58 uiB64 = uB.s.signExp;
59 uiB0 = uB.s.signif;
60 if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
61 if (
62 softfloat_isSigNaNExtF80UI( uiA64, uiA0 )
63 || softfloat_isSigNaNExtF80UI( uiB64, uiB0 )
64 ) {
65 softfloat_raiseFlags( softfloat_flag_invalid );
66 }
67 return false;
68 }
69 signA = signExtF80UI64( uiA64 );
70 signB = signExtF80UI64( uiB64 );
71 return
72 (signA != signB)
73 ? signA && (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0)
74 : ((uiA64 != uiB64) || (uiA0 != uiB0))
75 && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
76
77}
78
deps/SoftFloat-3e/source/extF80_mul.c deleted-158
...@@ -1,158 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44extFloat80_t extF80_mul( extFloat80_t a, extFloat80_t b )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 bool signA;
50 int_fast32_t expA;
51 uint_fast64_t sigA;
52 union { struct extFloat80M s; extFloat80_t f; } uB;
53 uint_fast16_t uiB64;
54 uint_fast64_t uiB0;
55 bool signB;
56 int_fast32_t expB;
57 uint_fast64_t sigB;
58 bool signZ;
59 uint_fast64_t magBits;
60 struct exp32_sig64 normExpSig;
61 int_fast32_t expZ;
62 struct uint128 sig128Z, uiZ;
63 uint_fast16_t uiZ64;
64 uint_fast64_t uiZ0;
65 union { struct extFloat80M s; extFloat80_t f; } uZ;
66
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 uA.f = a;
70 uiA64 = uA.s.signExp;
71 uiA0 = uA.s.signif;
72 signA = signExtF80UI64( uiA64 );
73 expA = expExtF80UI64( uiA64 );
74 sigA = uiA0;
75 uB.f = b;
76 uiB64 = uB.s.signExp;
77 uiB0 = uB.s.signif;
78 signB = signExtF80UI64( uiB64 );
79 expB = expExtF80UI64( uiB64 );
80 sigB = uiB0;
81 signZ = signA ^ signB;
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( expA == 0x7FFF ) {
85 if (
86 (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
87 || ((expB == 0x7FFF) && (sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
88 ) {
89 goto propagateNaN;
90 }
91 magBits = expB | sigB;
92 goto infArg;
93 }
94 if ( expB == 0x7FFF ) {
95 if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN;
96 magBits = expA | sigA;
97 goto infArg;
98 }
99 /*------------------------------------------------------------------------
100 *------------------------------------------------------------------------*/
101 if ( ! expA ) expA = 1;
102 if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) {
103 if ( ! sigA ) goto zero;
104 normExpSig = softfloat_normSubnormalExtF80Sig( sigA );
105 expA += normExpSig.exp;
106 sigA = normExpSig.sig;
107 }
108 if ( ! expB ) expB = 1;
109 if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) {
110 if ( ! sigB ) goto zero;
111 normExpSig = softfloat_normSubnormalExtF80Sig( sigB );
112 expB += normExpSig.exp;
113 sigB = normExpSig.sig;
114 }
115 /*------------------------------------------------------------------------
116 *------------------------------------------------------------------------*/
117 expZ = expA + expB - 0x3FFE;
118 sig128Z = softfloat_mul64To128( sigA, sigB );
119 if ( sig128Z.v64 < UINT64_C( 0x8000000000000000 ) ) {
120 --expZ;
121 sig128Z =
122 softfloat_add128(
123 sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0 );
124 }
125 return
126 softfloat_roundPackToExtF80(
127 signZ, expZ, sig128Z.v64, sig128Z.v0, extF80_roundingPrecision );
128 /*------------------------------------------------------------------------
129 *------------------------------------------------------------------------*/
130 propagateNaN:
131 uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 );
132 uiZ64 = uiZ.v64;
133 uiZ0 = uiZ.v0;
134 goto uiZ;
135 /*------------------------------------------------------------------------
136 *------------------------------------------------------------------------*/
137 infArg:
138 if ( ! magBits ) {
139 softfloat_raiseFlags( softfloat_flag_invalid );
140 uiZ64 = defaultNaNExtF80UI64;
141 uiZ0 = defaultNaNExtF80UI0;
142 } else {
143 uiZ64 = packToExtF80UI64( signZ, 0x7FFF );
144 uiZ0 = UINT64_C( 0x8000000000000000 );
145 }
146 goto uiZ;
147 /*------------------------------------------------------------------------
148 *------------------------------------------------------------------------*/
149 zero:
150 uiZ64 = packToExtF80UI64( signZ, 0 );
151 uiZ0 = 0;
152 uiZ:
153 uZ.s.signExp = uiZ64;
154 uZ.s.signif = uiZ0;
155 return uZ.f;
156
157}
158
deps/SoftFloat-3e/source/extF80_rem.c deleted-225
...@@ -1,225 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44extFloat80_t extF80_rem( extFloat80_t a, extFloat80_t b )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 bool signA;
50 int_fast32_t expA;
51 uint_fast64_t sigA;
52 union { struct extFloat80M s; extFloat80_t f; } uB;
53 uint_fast16_t uiB64;
54 uint_fast64_t uiB0;
55 int_fast32_t expB;
56 uint_fast64_t sigB;
57 struct exp32_sig64 normExpSig;
58 int_fast32_t expDiff;
59 struct uint128 rem, shiftedSigB;
60 uint_fast32_t q, recip32;
61 uint_fast64_t q64;
62 struct uint128 term, altRem, meanRem;
63 bool signRem;
64 struct uint128 uiZ;
65 uint_fast16_t uiZ64;
66 uint_fast64_t uiZ0;
67 union { struct extFloat80M s; extFloat80_t f; } uZ;
68
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 uA.f = a;
72 uiA64 = uA.s.signExp;
73 uiA0 = uA.s.signif;
74 signA = signExtF80UI64( uiA64 );
75 expA = expExtF80UI64( uiA64 );
76 sigA = uiA0;
77 uB.f = b;
78 uiB64 = uB.s.signExp;
79 uiB0 = uB.s.signif;
80 expB = expExtF80UI64( uiB64 );
81 sigB = uiB0;
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( expA == 0x7FFF ) {
85 if (
86 (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
87 || ((expB == 0x7FFF) && (sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
88 ) {
89 goto propagateNaN;
90 }
91 goto invalid;
92 }
93 if ( expB == 0x7FFF ) {
94 if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN;
95 /*--------------------------------------------------------------------
96 | Argument b is an infinity. Doubling `expB' is an easy way to ensure
97 | that `expDiff' later is less than -1, which will result in returning
98 | a canonicalized version of argument a.
99 *--------------------------------------------------------------------*/
100 expB += expB;
101 }
102 /*------------------------------------------------------------------------
103 *------------------------------------------------------------------------*/
104 if ( ! expB ) expB = 1;
105 if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) {
106 if ( ! sigB ) goto invalid;
107 normExpSig = softfloat_normSubnormalExtF80Sig( sigB );
108 expB += normExpSig.exp;
109 sigB = normExpSig.sig;
110 }
111 if ( ! expA ) expA = 1;
112 if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) {
113 if ( ! sigA ) {
114 expA = 0;
115 goto copyA;
116 }
117 normExpSig = softfloat_normSubnormalExtF80Sig( sigA );
118 expA += normExpSig.exp;
119 sigA = normExpSig.sig;
120 }
121 /*------------------------------------------------------------------------
122 *------------------------------------------------------------------------*/
123 expDiff = expA - expB;
124 if ( expDiff < -1 ) goto copyA;
125 rem = softfloat_shortShiftLeft128( 0, sigA, 32 );
126 shiftedSigB = softfloat_shortShiftLeft128( 0, sigB, 32 );
127 if ( expDiff < 1 ) {
128 if ( expDiff ) {
129 --expB;
130 shiftedSigB = softfloat_shortShiftLeft128( 0, sigB, 33 );
131 q = 0;
132 } else {
133 q = (sigB <= sigA);
134 if ( q ) {
135 rem =
136 softfloat_sub128(
137 rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 );
138 }
139 }
140 } else {
141 recip32 = softfloat_approxRecip32_1( sigB>>32 );
142 expDiff -= 30;
143 for (;;) {
144 q64 = (uint_fast64_t) (uint32_t) (rem.v64>>2) * recip32;
145 if ( expDiff < 0 ) break;
146 q = (q64 + 0x80000000)>>32;
147 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
148 term = softfloat_mul64ByShifted32To128( sigB, q );
149 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
150 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
151 rem =
152 softfloat_add128(
153 rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 );
154 }
155 expDiff -= 29;
156 }
157 /*--------------------------------------------------------------------
158 | (`expDiff' cannot be less than -29 here.)
159 *--------------------------------------------------------------------*/
160 q = (uint32_t) (q64>>32)>>(~expDiff & 31);
161 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, expDiff + 30 );
162 term = softfloat_mul64ByShifted32To128( sigB, q );
163 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
164 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
165 altRem =
166 softfloat_add128(
167 rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 );
168 goto selectRem;
169 }
170 }
171 /*------------------------------------------------------------------------
172 *------------------------------------------------------------------------*/
173 do {
174 altRem = rem;
175 ++q;
176 rem =
177 softfloat_sub128(
178 rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 );
179 } while ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) );
180 selectRem:
181 meanRem = softfloat_add128( rem.v64, rem.v0, altRem.v64, altRem.v0 );
182 if (
183 (meanRem.v64 & UINT64_C( 0x8000000000000000 ))
184 || (! (meanRem.v64 | meanRem.v0) && (q & 1))
185 ) {
186 rem = altRem;
187 }
188 signRem = signA;
189 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
190 signRem = ! signRem;
191 rem = softfloat_sub128( 0, 0, rem.v64, rem.v0 );
192 }
193 return
194 softfloat_normRoundPackToExtF80(
195 signRem, rem.v64 | rem.v0 ? expB + 32 : 0, rem.v64, rem.v0, 80 );
196 /*------------------------------------------------------------------------
197 *------------------------------------------------------------------------*/
198 propagateNaN:
199 uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 );
200 uiZ64 = uiZ.v64;
201 uiZ0 = uiZ.v0;
202 goto uiZ;
203 /*------------------------------------------------------------------------
204 *------------------------------------------------------------------------*/
205 invalid:
206 softfloat_raiseFlags( softfloat_flag_invalid );
207 uiZ64 = defaultNaNExtF80UI64;
208 uiZ0 = defaultNaNExtF80UI0;
209 goto uiZ;
210 /*------------------------------------------------------------------------
211 *------------------------------------------------------------------------*/
212 copyA:
213 if ( expA < 1 ) {
214 sigA >>= 1 - expA;
215 expA = 0;
216 }
217 uiZ64 = packToExtF80UI64( signA, expA );
218 uiZ0 = sigA;
219 uiZ:
220 uZ.s.signExp = uiZ64;
221 uZ.s.signif = uiZ0;
222 return uZ.f;
223
224}
225
deps/SoftFloat-3e/source/extF80_roundToInt.c deleted-154
...@@ -1,154 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44extFloat80_t
45 extF80_roundToInt( extFloat80_t a, uint_fast8_t roundingMode, bool exact )
46{
47 union { struct extFloat80M s; extFloat80_t f; } uA;
48 uint_fast16_t uiA64, signUI64;
49 int_fast32_t exp;
50 uint_fast64_t sigA;
51 uint_fast16_t uiZ64;
52 uint_fast64_t sigZ;
53 struct exp32_sig64 normExpSig;
54 struct uint128 uiZ;
55 uint_fast64_t lastBitMask, roundBitsMask;
56 union { struct extFloat80M s; extFloat80_t f; } uZ;
57
58 /*------------------------------------------------------------------------
59 *------------------------------------------------------------------------*/
60 uA.f = a;
61 uiA64 = uA.s.signExp;
62 signUI64 = uiA64 & packToExtF80UI64( 1, 0 );
63 exp = expExtF80UI64( uiA64 );
64 sigA = uA.s.signif;
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 if ( !(sigA & UINT64_C( 0x8000000000000000 )) && (exp != 0x7FFF) ) {
68 if ( !sigA ) {
69 uiZ64 = signUI64;
70 sigZ = 0;
71 goto uiZ;
72 }
73 normExpSig = softfloat_normSubnormalExtF80Sig( sigA );
74 exp += normExpSig.exp;
75 sigA = normExpSig.sig;
76 }
77 /*------------------------------------------------------------------------
78 *------------------------------------------------------------------------*/
79 if ( 0x403E <= exp ) {
80 if ( exp == 0x7FFF ) {
81 if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
82 uiZ = softfloat_propagateNaNExtF80UI( uiA64, sigA, 0, 0 );
83 uiZ64 = uiZ.v64;
84 sigZ = uiZ.v0;
85 goto uiZ;
86 }
87 sigZ = UINT64_C( 0x8000000000000000 );
88 } else {
89 sigZ = sigA;
90 }
91 uiZ64 = signUI64 | exp;
92 goto uiZ;
93 }
94 if ( exp <= 0x3FFE ) {
95 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
96 switch ( roundingMode ) {
97 case softfloat_round_near_even:
98 if ( !(sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) break;
99 case softfloat_round_near_maxMag:
100 if ( exp == 0x3FFE ) goto mag1;
101 break;
102 case softfloat_round_min:
103 if ( signUI64 ) goto mag1;
104 break;
105 case softfloat_round_max:
106 if ( !signUI64 ) goto mag1;
107 break;
108#ifdef SOFTFLOAT_ROUND_ODD
109 case softfloat_round_odd:
110 goto mag1;
111#endif
112 }
113 uiZ64 = signUI64;
114 sigZ = 0;
115 goto uiZ;
116 mag1:
117 uiZ64 = signUI64 | 0x3FFF;
118 sigZ = UINT64_C( 0x8000000000000000 );
119 goto uiZ;
120 }
121 /*------------------------------------------------------------------------
122 *------------------------------------------------------------------------*/
123 uiZ64 = signUI64 | exp;
124 lastBitMask = (uint_fast64_t) 1<<(0x403E - exp);
125 roundBitsMask = lastBitMask - 1;
126 sigZ = sigA;
127 if ( roundingMode == softfloat_round_near_maxMag ) {
128 sigZ += lastBitMask>>1;
129 } else if ( roundingMode == softfloat_round_near_even ) {
130 sigZ += lastBitMask>>1;
131 if ( !(sigZ & roundBitsMask) ) sigZ &= ~lastBitMask;
132 } else if (
133 roundingMode == (signUI64 ? softfloat_round_min : softfloat_round_max)
134 ) {
135 sigZ += roundBitsMask;
136 }
137 sigZ &= ~roundBitsMask;
138 if ( !sigZ ) {
139 ++uiZ64;
140 sigZ = UINT64_C( 0x8000000000000000 );
141 }
142 if ( sigZ != sigA ) {
143#ifdef SOFTFLOAT_ROUND_ODD
144 if ( roundingMode == softfloat_round_odd ) sigZ |= lastBitMask;
145#endif
146 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
147 }
148 uiZ:
149 uZ.s.signExp = uiZ64;
150 uZ.s.signif = sigZ;
151 return uZ.f;
152
153}
154
deps/SoftFloat-3e/source/extF80_sqrt.c deleted-176
...@@ -1,176 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44extFloat80_t extF80_sqrt( extFloat80_t a )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 bool signA;
50 int_fast32_t expA;
51 uint_fast64_t sigA;
52 struct uint128 uiZ;
53 uint_fast16_t uiZ64;
54 uint_fast64_t uiZ0;
55 struct exp32_sig64 normExpSig;
56 int_fast32_t expZ;
57 uint_fast32_t sig32A, recipSqrt32, sig32Z;
58 struct uint128 rem;
59 uint_fast64_t q, x64, sigZ;
60 struct uint128 y, term;
61 uint_fast64_t sigZExtra;
62 union { struct extFloat80M s; extFloat80_t f; } uZ;
63
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 uA.f = a;
67 uiA64 = uA.s.signExp;
68 uiA0 = uA.s.signif;
69 signA = signExtF80UI64( uiA64 );
70 expA = expExtF80UI64( uiA64 );
71 sigA = uiA0;
72 /*------------------------------------------------------------------------
73 *------------------------------------------------------------------------*/
74 if ( expA == 0x7FFF ) {
75 if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
76 uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, 0, 0 );
77 uiZ64 = uiZ.v64;
78 uiZ0 = uiZ.v0;
79 goto uiZ;
80 }
81 if ( ! signA ) return a;
82 goto invalid;
83 }
84 /*------------------------------------------------------------------------
85 *------------------------------------------------------------------------*/
86 if ( signA ) {
87 if ( ! sigA ) goto zero;
88 goto invalid;
89 }
90 /*------------------------------------------------------------------------
91 *------------------------------------------------------------------------*/
92 if ( ! expA ) expA = 1;
93 if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) {
94 if ( ! sigA ) goto zero;
95 normExpSig = softfloat_normSubnormalExtF80Sig( sigA );
96 expA += normExpSig.exp;
97 sigA = normExpSig.sig;
98 }
99 /*------------------------------------------------------------------------
100 | (`sig32Z' is guaranteed to be a lower bound on the square root of
101 | `sig32A', which makes `sig32Z' also a lower bound on the square root of
102 | `sigA'.)
103 *------------------------------------------------------------------------*/
104 expZ = ((expA - 0x3FFF)>>1) + 0x3FFF;
105 expA &= 1;
106 sig32A = sigA>>32;
107 recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A );
108 sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32;
109 if ( expA ) {
110 sig32Z >>= 1;
111 rem = softfloat_shortShiftLeft128( 0, sigA, 61 );
112 } else {
113 rem = softfloat_shortShiftLeft128( 0, sigA, 62 );
114 }
115 rem.v64 -= (uint_fast64_t) sig32Z * sig32Z;
116 /*------------------------------------------------------------------------
117 *------------------------------------------------------------------------*/
118 q = ((uint32_t) (rem.v64>>2) * (uint_fast64_t) recipSqrt32)>>32;
119 x64 = (uint_fast64_t) sig32Z<<32;
120 sigZ = x64 + (q<<3);
121 y = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
122 /*------------------------------------------------------------------------
123 | (Repeating this loop is a rare occurrence.)
124 *------------------------------------------------------------------------*/
125 for (;;) {
126 term = softfloat_mul64ByShifted32To128( x64 + sigZ, q );
127 rem = softfloat_sub128( y.v64, y.v0, term.v64, term.v0 );
128 if ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ) break;
129 --q;
130 sigZ -= 1<<3;
131 }
132 /*------------------------------------------------------------------------
133 *------------------------------------------------------------------------*/
134 q = (((rem.v64>>2) * recipSqrt32)>>32) + 2;
135 x64 = sigZ;
136 sigZ = (sigZ<<1) + (q>>25);
137 sigZExtra = (uint64_t) (q<<39);
138 /*------------------------------------------------------------------------
139 *------------------------------------------------------------------------*/
140 if ( (q & 0xFFFFFF) <= 2 ) {
141 q &= ~(uint_fast64_t) 0xFFFF;
142 sigZExtra = (uint64_t) (q<<39);
143 term = softfloat_mul64ByShifted32To128( x64 + (q>>27), q );
144 x64 = (uint32_t) (q<<5) * (uint_fast64_t) (uint32_t) q;
145 term = softfloat_add128( term.v64, term.v0, 0, x64 );
146 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 28 );
147 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
148 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
149 if ( ! sigZExtra ) --sigZ;
150 --sigZExtra;
151 } else {
152 if ( rem.v64 | rem.v0 ) sigZExtra |= 1;
153 }
154 }
155 return
156 softfloat_roundPackToExtF80(
157 0, expZ, sigZ, sigZExtra, extF80_roundingPrecision );
158 /*------------------------------------------------------------------------
159 *------------------------------------------------------------------------*/
160 invalid:
161 softfloat_raiseFlags( softfloat_flag_invalid );
162 uiZ64 = defaultNaNExtF80UI64;
163 uiZ0 = defaultNaNExtF80UI0;
164 goto uiZ;
165 /*------------------------------------------------------------------------
166 *------------------------------------------------------------------------*/
167 zero:
168 uiZ64 = packToExtF80UI64( signA, 0 );
169 uiZ0 = 0;
170 uiZ:
171 uZ.s.signExp = uiZ64;
172 uZ.s.signif = uiZ0;
173 return uZ.f;
174
175}
176
deps/SoftFloat-3e/source/extF80_sub.c deleted-80
...@@ -1,80 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43extFloat80_t extF80_sub( extFloat80_t a, extFloat80_t b )
44{
45 union { struct extFloat80M s; extFloat80_t f; } uA;
46 uint_fast16_t uiA64;
47 uint_fast64_t uiA0;
48 bool signA;
49 union { struct extFloat80M s; extFloat80_t f; } uB;
50 uint_fast16_t uiB64;
51 uint_fast64_t uiB0;
52 bool signB;
53#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
54 extFloat80_t
55 (*magsFuncPtr)(
56 uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool );
57#endif
58
59 uA.f = a;
60 uiA64 = uA.s.signExp;
61 uiA0 = uA.s.signif;
62 signA = signExtF80UI64( uiA64 );
63 uB.f = b;
64 uiB64 = uB.s.signExp;
65 uiB0 = uB.s.signif;
66 signB = signExtF80UI64( uiB64 );
67#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
68 if ( signA == signB ) {
69 return softfloat_subMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA );
70 } else {
71 return softfloat_addMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA );
72 }
73#else
74 magsFuncPtr =
75 (signA == signB) ? softfloat_subMagsExtF80 : softfloat_addMagsExtF80;
76 return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
77#endif
78
79}
80
deps/SoftFloat-3e/source/extF80_to_f128.c deleted-75
...@@ -1,75 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float128_t extF80_to_f128( extFloat80_t a )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 uint_fast16_t exp;
50 uint_fast64_t frac;
51 struct commonNaN commonNaN;
52 struct uint128 uiZ;
53 bool sign;
54 struct uint128 frac128;
55 union ui128_f128 uZ;
56
57 uA.f = a;
58 uiA64 = uA.s.signExp;
59 uiA0 = uA.s.signif;
60 exp = expExtF80UI64( uiA64 );
61 frac = uiA0 & UINT64_C( 0x7FFFFFFFFFFFFFFF );
62 if ( (exp == 0x7FFF) && frac ) {
63 softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN );
64 uiZ = softfloat_commonNaNToF128UI( &commonNaN );
65 } else {
66 sign = signExtF80UI64( uiA64 );
67 frac128 = softfloat_shortShiftLeft128( 0, frac, 49 );
68 uiZ.v64 = packToF128UI64( sign, exp, frac128.v64 );
69 uiZ.v0 = frac128.v0;
70 }
71 uZ.ui = uiZ;
72 return uZ.f;
73
74}
75
deps/SoftFloat-3e/source/extF80_to_f16.c deleted-96
...@@ -1,96 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float16_t extF80_to_f16( extFloat80_t a )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 bool sign;
50 int_fast32_t exp;
51 uint_fast64_t sig;
52 struct commonNaN commonNaN;
53 uint_fast16_t uiZ, sig16;
54 union ui16_f16 uZ;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 uA.f = a;
59 uiA64 = uA.s.signExp;
60 uiA0 = uA.s.signif;
61 sign = signExtF80UI64( uiA64 );
62 exp = expExtF80UI64( uiA64 );
63 sig = uiA0;
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 if ( exp == 0x7FFF ) {
67 if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
68 softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN );
69 uiZ = softfloat_commonNaNToF16UI( &commonNaN );
70 } else {
71 uiZ = packToF16UI( sign, 0x1F, 0 );
72 }
73 goto uiZ;
74 }
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 sig16 = softfloat_shortShiftRightJam64( sig, 49 );
78 if ( ! (exp | sig16) ) {
79 uiZ = packToF16UI( sign, 0, 0 );
80 goto uiZ;
81 }
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 exp -= 0x3FF1;
85 if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
86 if ( exp < -0x40 ) exp = -0x40;
87 }
88 return softfloat_roundPackToF16( sign, exp, sig16 );
89 /*------------------------------------------------------------------------
90 *------------------------------------------------------------------------*/
91 uiZ:
92 uZ.ui = uiZ;
93 return uZ.f;
94
95}
96
deps/SoftFloat-3e/source/extF80_to_f32.c deleted-96
...@@ -1,96 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float32_t extF80_to_f32( extFloat80_t a )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 bool sign;
50 int_fast32_t exp;
51 uint_fast64_t sig;
52 struct commonNaN commonNaN;
53 uint_fast32_t uiZ, sig32;
54 union ui32_f32 uZ;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 uA.f = a;
59 uiA64 = uA.s.signExp;
60 uiA0 = uA.s.signif;
61 sign = signExtF80UI64( uiA64 );
62 exp = expExtF80UI64( uiA64 );
63 sig = uiA0;
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 if ( exp == 0x7FFF ) {
67 if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
68 softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN );
69 uiZ = softfloat_commonNaNToF32UI( &commonNaN );
70 } else {
71 uiZ = packToF32UI( sign, 0xFF, 0 );
72 }
73 goto uiZ;
74 }
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 sig32 = softfloat_shortShiftRightJam64( sig, 33 );
78 if ( ! (exp | sig32) ) {
79 uiZ = packToF32UI( sign, 0, 0 );
80 goto uiZ;
81 }
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 exp -= 0x3F81;
85 if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
86 if ( exp < -0x1000 ) exp = -0x1000;
87 }
88 return softfloat_roundPackToF32( sign, exp, sig32 );
89 /*------------------------------------------------------------------------
90 *------------------------------------------------------------------------*/
91 uiZ:
92 uZ.ui = uiZ;
93 return uZ.f;
94
95}
96
deps/SoftFloat-3e/source/extF80_to_f64.c deleted-96
...@@ -1,96 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float64_t extF80_to_f64( extFloat80_t a )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 bool sign;
50 int_fast32_t exp;
51 uint_fast64_t sig;
52 struct commonNaN commonNaN;
53 uint_fast64_t uiZ;
54 union ui64_f64 uZ;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 uA.f = a;
59 uiA64 = uA.s.signExp;
60 uiA0 = uA.s.signif;
61 sign = signExtF80UI64( uiA64 );
62 exp = expExtF80UI64( uiA64 );
63 sig = uiA0;
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 if ( ! (exp | sig) ) {
67 uiZ = packToF64UI( sign, 0, 0 );
68 goto uiZ;
69 }
70 /*------------------------------------------------------------------------
71 *------------------------------------------------------------------------*/
72 if ( exp == 0x7FFF ) {
73 if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
74 softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN );
75 uiZ = softfloat_commonNaNToF64UI( &commonNaN );
76 } else {
77 uiZ = packToF64UI( sign, 0x7FF, 0 );
78 }
79 goto uiZ;
80 }
81 /*------------------------------------------------------------------------
82 *------------------------------------------------------------------------*/
83 sig = softfloat_shortShiftRightJam64( sig, 1 );
84 exp -= 0x3C01;
85 if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
86 if ( exp < -0x1000 ) exp = -0x1000;
87 }
88 return softfloat_roundPackToF64( sign, exp, sig );
89 /*------------------------------------------------------------------------
90 *------------------------------------------------------------------------*/
91 uiZ:
92 uZ.ui = uiZ;
93 return uZ.f;
94
95}
96
deps/SoftFloat-3e/source/extF80_to_i32.c deleted-83
...@@ -1,83 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast32_t
45 extF80_to_i32( extFloat80_t a, uint_fast8_t roundingMode, bool exact )
46{
47 union { struct extFloat80M s; extFloat80_t f; } uA;
48 uint_fast16_t uiA64;
49 bool sign;
50 int_fast32_t exp;
51 uint_fast64_t sig;
52 int_fast32_t shiftDist;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA64 = uA.s.signExp;
58 sign = signExtF80UI64( uiA64 );
59 exp = expExtF80UI64( uiA64 );
60 sig = uA.s.signif;
61 /*------------------------------------------------------------------------
62 *------------------------------------------------------------------------*/
63#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
64 if ( (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) {
65#if (i32_fromNaN == i32_fromPosOverflow)
66 sign = 0;
67#elif (i32_fromNaN == i32_fromNegOverflow)
68 sign = 1;
69#else
70 softfloat_raiseFlags( softfloat_flag_invalid );
71 return i32_fromNaN;
72#endif
73 }
74#endif
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 shiftDist = 0x4032 - exp;
78 if ( shiftDist <= 0 ) shiftDist = 1;
79 sig = softfloat_shiftRightJam64( sig, shiftDist );
80 return softfloat_roundToI32( sign, sig, roundingMode, exact );
81
82}
83
deps/SoftFloat-3e/source/extF80_to_i32_r_minMag.c deleted-97
...@@ -1,97 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast32_t extF80_to_i32_r_minMag( extFloat80_t a, bool exact )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 int_fast32_t exp;
49 uint_fast64_t sig;
50 int_fast32_t shiftDist;
51 bool sign;
52 int_fast32_t absZ;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA64 = uA.s.signExp;
58 exp = expExtF80UI64( uiA64 );
59 sig = uA.s.signif;
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = 0x403E - exp;
63 if ( 64 <= shiftDist ) {
64 if ( exact && (exp | sig) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signExtF80UI64( uiA64 );
72 if ( shiftDist < 33 ) {
73 if (
74 (uiA64 == packToExtF80UI64( 1, 0x401E ))
75 && (sig < UINT64_C( 0x8000000100000000 ))
76 ) {
77 if ( exact && (sig & UINT64_C( 0x00000000FFFFFFFF )) ) {
78 softfloat_exceptionFlags |= softfloat_flag_inexact;
79 }
80 return -0x7FFFFFFF - 1;
81 }
82 softfloat_raiseFlags( softfloat_flag_invalid );
83 return
84 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
85 ? i32_fromNaN
86 : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
87 }
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 absZ = sig>>shiftDist;
91 if ( exact && ((uint_fast64_t) (uint_fast32_t) absZ<<shiftDist != sig) ) {
92 softfloat_exceptionFlags |= softfloat_flag_inexact;
93 }
94 return sign ? -absZ : absZ;
95
96}
97
deps/SoftFloat-3e/source/extF80_to_i64.c deleted-89
...@@ -1,89 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast64_t
45 extF80_to_i64( extFloat80_t a, uint_fast8_t roundingMode, bool exact )
46{
47 union { struct extFloat80M s; extFloat80_t f; } uA;
48 uint_fast16_t uiA64;
49 bool sign;
50 int_fast32_t exp;
51 uint_fast64_t sig;
52 int_fast32_t shiftDist;
53 uint_fast64_t sigExtra;
54 struct uint64_extra sig64Extra;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 uA.f = a;
59 uiA64 = uA.s.signExp;
60 sign = signExtF80UI64( uiA64 );
61 exp = expExtF80UI64( uiA64 );
62 sig = uA.s.signif;
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 shiftDist = 0x403E - exp;
66 if ( shiftDist <= 0 ) {
67 /*--------------------------------------------------------------------
68 *--------------------------------------------------------------------*/
69 if ( shiftDist ) {
70 softfloat_raiseFlags( softfloat_flag_invalid );
71 return
72 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
73 ? i64_fromNaN
74 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
75 }
76 /*--------------------------------------------------------------------
77 *--------------------------------------------------------------------*/
78 sigExtra = 0;
79 } else {
80 /*--------------------------------------------------------------------
81 *--------------------------------------------------------------------*/
82 sig64Extra = softfloat_shiftRightJam64Extra( sig, 0, shiftDist );
83 sig = sig64Extra.v;
84 sigExtra = sig64Extra.extra;
85 }
86 return softfloat_roundToI64( sign, sig, sigExtra, roundingMode, exact );
87
88}
89
deps/SoftFloat-3e/source/extF80_to_i64_r_minMag.c deleted-94
...@@ -1,94 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast64_t extF80_to_i64_r_minMag( extFloat80_t a, bool exact )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 int_fast32_t exp;
49 uint_fast64_t sig;
50 int_fast32_t shiftDist;
51 bool sign;
52 int_fast64_t absZ;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA64 = uA.s.signExp;
58 exp = expExtF80UI64( uiA64 );
59 sig = uA.s.signif;
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = 0x403E - exp;
63 if ( 64 <= shiftDist ) {
64 if ( exact && (exp | sig) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signExtF80UI64( uiA64 );
72 if ( shiftDist <= 0 ) {
73 if (
74 (uiA64 == packToExtF80UI64( 1, 0x403E ))
75 && (sig == UINT64_C( 0x8000000000000000 ))
76 ) {
77 return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1;
78 }
79 softfloat_raiseFlags( softfloat_flag_invalid );
80 return
81 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
82 ? i64_fromNaN
83 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
84 }
85 /*------------------------------------------------------------------------
86 *------------------------------------------------------------------------*/
87 absZ = sig>>shiftDist;
88 if ( exact && (uint64_t) (sig<<(-shiftDist & 63)) ) {
89 softfloat_exceptionFlags |= softfloat_flag_inexact;
90 }
91 return sign ? -absZ : absZ;
92
93}
94
deps/SoftFloat-3e/source/extF80_to_ui32.c deleted-83
...@@ -1,83 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast32_t
45 extF80_to_ui32( extFloat80_t a, uint_fast8_t roundingMode, bool exact )
46{
47 union { struct extFloat80M s; extFloat80_t f; } uA;
48 uint_fast16_t uiA64;
49 bool sign;
50 int_fast32_t exp;
51 uint_fast64_t sig;
52 int_fast32_t shiftDist;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA64 = uA.s.signExp;
58 sign = signExtF80UI64( uiA64 );
59 exp = expExtF80UI64( uiA64 );
60 sig = uA.s.signif;
61 /*------------------------------------------------------------------------
62 *------------------------------------------------------------------------*/
63#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
64 if ( (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) {
65#if (ui32_fromNaN == ui32_fromPosOverflow)
66 sign = 0;
67#elif (ui32_fromNaN == ui32_fromNegOverflow)
68 sign = 1;
69#else
70 softfloat_raiseFlags( softfloat_flag_invalid );
71 return ui32_fromNaN;
72#endif
73 }
74#endif
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 shiftDist = 0x4032 - exp;
78 if ( shiftDist <= 0 ) shiftDist = 1;
79 sig = softfloat_shiftRightJam64( sig, shiftDist );
80 return softfloat_roundToUI32( sign, sig, roundingMode, exact );
81
82}
83
deps/SoftFloat-3e/source/extF80_to_ui32_r_minMag.c deleted-88
...@@ -1,88 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t a, bool exact )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 int_fast32_t exp;
49 uint_fast64_t sig;
50 int_fast32_t shiftDist;
51 bool sign;
52 uint_fast32_t z;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA64 = uA.s.signExp;
58 exp = expExtF80UI64( uiA64 );
59 sig = uA.s.signif;
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = 0x403E - exp;
63 if ( 64 <= shiftDist ) {
64 if ( exact && (exp | sig) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signExtF80UI64( uiA64 );
72 if ( sign || (shiftDist < 32) ) {
73 softfloat_raiseFlags( softfloat_flag_invalid );
74 return
75 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
76 ? ui32_fromNaN
77 : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
78 }
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 z = sig>>shiftDist;
82 if ( exact && ((uint_fast64_t) z<<shiftDist != sig) ) {
83 softfloat_exceptionFlags |= softfloat_flag_inexact;
84 }
85 return z;
86
87}
88
deps/SoftFloat-3e/source/extF80_to_ui64.c deleted-84
...@@ -1,84 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast64_t
45 extF80_to_ui64( extFloat80_t a, uint_fast8_t roundingMode, bool exact )
46{
47 union { struct extFloat80M s; extFloat80_t f; } uA;
48 uint_fast16_t uiA64;
49 bool sign;
50 int_fast32_t exp;
51 uint_fast64_t sig;
52 int_fast32_t shiftDist;
53 uint_fast64_t sigExtra;
54 struct uint64_extra sig64Extra;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 uA.f = a;
59 uiA64 = uA.s.signExp;
60 sign = signExtF80UI64( uiA64 );
61 exp = expExtF80UI64( uiA64 );
62 sig = uA.s.signif;
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 shiftDist = 0x403E - exp;
66 if ( shiftDist < 0 ) {
67 softfloat_raiseFlags( softfloat_flag_invalid );
68 return
69 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
70 ? ui64_fromNaN
71 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
72 }
73 /*------------------------------------------------------------------------
74 *------------------------------------------------------------------------*/
75 sigExtra = 0;
76 if ( shiftDist ) {
77 sig64Extra = softfloat_shiftRightJam64Extra( sig, 0, shiftDist );
78 sig = sig64Extra.v;
79 sigExtra = sig64Extra.extra;
80 }
81 return softfloat_roundToUI64( sign, sig, sigExtra, roundingMode, exact );
82
83}
84
deps/SoftFloat-3e/source/extF80_to_ui64_r_minMag.c deleted-88
...@@ -1,88 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t a, bool exact )
45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 int_fast32_t exp;
49 uint_fast64_t sig;
50 int_fast32_t shiftDist;
51 bool sign;
52 uint_fast64_t z;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA64 = uA.s.signExp;
58 exp = expExtF80UI64( uiA64 );
59 sig = uA.s.signif;
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = 0x403E - exp;
63 if ( 64 <= shiftDist ) {
64 if ( exact && (exp | sig) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signExtF80UI64( uiA64 );
72 if ( sign || (shiftDist < 0) ) {
73 softfloat_raiseFlags( softfloat_flag_invalid );
74 return
75 (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
76 ? ui64_fromNaN
77 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
78 }
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 z = sig>>shiftDist;
82 if ( exact && (z<<shiftDist != sig) ) {
83 softfloat_exceptionFlags |= softfloat_flag_inexact;
84 }
85 return z;
86
87}
88
deps/SoftFloat-3e/source/f128M_add.c deleted-97
...@@ -1,97 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43#ifdef SOFTFLOAT_FAST_INT64
44
45void
46 f128M_add( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
47{
48 const uint64_t *aWPtr, *bWPtr;
49 uint_fast64_t uiA64, uiA0;
50 bool signA;
51 uint_fast64_t uiB64, uiB0;
52 bool signB;
53#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
54 float128_t
55 (*magsFuncPtr)(
56 uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
57#endif
58
59 aWPtr = (const uint64_t *) aPtr;
60 bWPtr = (const uint64_t *) bPtr;
61 uiA64 = aWPtr[indexWord( 2, 1 )];
62 uiA0 = aWPtr[indexWord( 2, 0 )];
63 signA = signF128UI64( uiA64 );
64 uiB64 = bWPtr[indexWord( 2, 1 )];
65 uiB0 = bWPtr[indexWord( 2, 0 )];
66 signB = signF128UI64( uiB64 );
67#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
68 if ( signA == signB ) {
69 *zPtr = softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
70 } else {
71 *zPtr = softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
72 }
73#else
74 magsFuncPtr =
75 (signA == signB) ? softfloat_addMagsF128 : softfloat_subMagsF128;
76 *zPtr = (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
77#endif
78
79}
80
81#else
82
83void
84 f128M_add( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
85{
86
87 softfloat_addF128M(
88 (const uint32_t *) aPtr,
89 (const uint32_t *) bPtr,
90 (uint32_t *) zPtr,
91 false
92 );
93
94}
95
96#endif
97
deps/SoftFloat-3e/source/f128M_div.c deleted-187
...@@ -1,187 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void
47 f128M_div( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
48{
49
50 *zPtr = f128_div( *aPtr, *bPtr );
51
52}
53
54#else
55
56void
57 f128M_div( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
58{
59 const uint32_t *aWPtr, *bWPtr;
60 uint32_t *zWPtr, uiA96;
61 bool signA;
62 int32_t expA;
63 uint32_t uiB96;
64 bool signB;
65 int32_t expB;
66 bool signZ;
67 uint32_t y[5], sigB[4];
68 int32_t expZ;
69 uint32_t recip32;
70 int ix;
71 uint64_t q64;
72 uint32_t q, qs[3], uiZ96;
73
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 aWPtr = (const uint32_t *) aPtr;
77 bWPtr = (const uint32_t *) bPtr;
78 zWPtr = (uint32_t *) zPtr;
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 uiA96 = aWPtr[indexWordHi( 4 )];
82 signA = signF128UI96( uiA96 );
83 expA = expF128UI96( uiA96 );
84 uiB96 = bWPtr[indexWordHi( 4 )];
85 signB = signF128UI96( uiB96 );
86 expB = expF128UI96( uiB96 );
87 signZ = signA ^ signB;
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
91 if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return;
92 if ( expA == 0x7FFF ) {
93 if ( expB == 0x7FFF ) goto invalid;
94 goto infinity;
95 }
96 goto zero;
97 }
98 /*------------------------------------------------------------------------
99 *------------------------------------------------------------------------*/
100 expA = softfloat_shiftNormSigF128M( aWPtr, 13, y );
101 expB = softfloat_shiftNormSigF128M( bWPtr, 13, sigB );
102 if ( expA == -128 ) {
103 if ( expB == -128 ) goto invalid;
104 goto zero;
105 }
106 if ( expB == -128 ) {
107 softfloat_raiseFlags( softfloat_flag_infinite );
108 goto infinity;
109 }
110 /*------------------------------------------------------------------------
111 *------------------------------------------------------------------------*/
112 expZ = expA - expB + 0x3FFE;
113 if ( softfloat_compare128M( y, sigB ) < 0 ) {
114 --expZ;
115 softfloat_add128M( y, y, y );
116 }
117 recip32 =
118 softfloat_approxRecip32_1(
119 ((uint64_t) sigB[indexWord( 4, 3 )]<<32 | sigB[indexWord( 4, 2 )])
120 >>30
121 );
122 ix = 3;
123 for (;;) {
124 q64 = (uint64_t) y[indexWordHi( 4 )] * recip32;
125 q = (q64 + 0x80000000)>>32;
126 --ix;
127 if ( ix < 0 ) break;
128 softfloat_remStep128MBy32( y, 29, sigB, q, y );
129 if ( y[indexWordHi( 4 )] & 0x80000000 ) {
130 --q;
131 softfloat_add128M( y, sigB, y );
132 }
133 qs[ix] = q;
134 }
135 /*------------------------------------------------------------------------
136 *------------------------------------------------------------------------*/
137 if ( ((q + 1) & 7) < 2 ) {
138 softfloat_remStep128MBy32( y, 29, sigB, q, y );
139 if ( y[indexWordHi( 4 )] & 0x80000000 ) {
140 --q;
141 softfloat_add128M( y, sigB, y );
142 } else if ( softfloat_compare128M( sigB, y ) <= 0 ) {
143 ++q;
144 softfloat_sub128M( y, sigB, y );
145 }
146 if (
147 y[indexWordLo( 4 )] || y[indexWord( 4, 1 )]
148 || (y[indexWord( 4, 2 )] | y[indexWord( 4, 3 )])
149 ) {
150 q |= 1;
151 }
152 }
153 /*------------------------------------------------------------------------
154 *------------------------------------------------------------------------*/
155 q64 = (uint64_t) q<<28;
156 y[indexWord( 5, 0 )] = q64;
157 q64 = ((uint64_t) qs[0]<<25) + (q64>>32);
158 y[indexWord( 5, 1 )] = q64;
159 q64 = ((uint64_t) qs[1]<<22) + (q64>>32);
160 y[indexWord( 5, 2 )] = q64;
161 q64 = ((uint64_t) qs[2]<<19) + (q64>>32);
162 y[indexWord( 5, 3 )] = q64;
163 y[indexWord( 5, 4 )] = q64>>32;
164 softfloat_roundPackMToF128M( signZ, expZ, y, zWPtr );
165 return;
166 /*------------------------------------------------------------------------
167 *------------------------------------------------------------------------*/
168 invalid:
169 softfloat_invalidF128M( zWPtr );
170 return;
171 /*------------------------------------------------------------------------
172 *------------------------------------------------------------------------*/
173 infinity:
174 uiZ96 = packToF128UI96( signZ, 0x7FFF, 0 );
175 goto uiZ96;
176 zero:
177 uiZ96 = packToF128UI96( signZ, 0, 0 );
178 uiZ96:
179 zWPtr[indexWordHi( 4 )] = uiZ96;
180 zWPtr[indexWord( 4, 2 )] = 0;
181 zWPtr[indexWord( 4, 1 )] = 0;
182 zWPtr[indexWord( 4, 0 )] = 0;
183
184}
185
186#endif
187
deps/SoftFloat-3e/source/f128M_eq.c deleted-100
...@@ -1,100 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46bool f128M_eq( const float128_t *aPtr, const float128_t *bPtr )
47{
48
49 return f128_eq( *aPtr, *bPtr );
50
51}
52
53#else
54
55bool f128M_eq( const float128_t *aPtr, const float128_t *bPtr )
56{
57 const uint32_t *aWPtr, *bWPtr;
58 uint32_t wordA, wordB, uiA96, uiB96;
59 bool possibleOppositeZeros;
60 uint32_t mashWord;
61
62 aWPtr = (const uint32_t *) aPtr;
63 bWPtr = (const uint32_t *) bPtr;
64 wordA = aWPtr[indexWord( 4, 2 )];
65 wordB = bWPtr[indexWord( 4, 2 )];
66 if ( wordA != wordB ) goto false_checkSigNaNs;
67 uiA96 = aWPtr[indexWordHi( 4 )];
68 uiB96 = bWPtr[indexWordHi( 4 )];
69 possibleOppositeZeros = false;
70 if ( uiA96 != uiB96 ) {
71 possibleOppositeZeros = (((uiA96 | uiB96) & 0x7FFFFFFF) == 0);
72 if ( ! possibleOppositeZeros ) goto false_checkSigNaNs;
73 }
74 mashWord = wordA | wordB;
75 wordA = aWPtr[indexWord( 4, 1 )];
76 wordB = bWPtr[indexWord( 4, 1 )];
77 if ( wordA != wordB ) goto false_checkSigNaNs;
78 mashWord |= wordA | wordB;
79 wordA = aWPtr[indexWord( 4, 0 )];
80 wordB = bWPtr[indexWord( 4, 0 )];
81 if ( wordA != wordB ) goto false_checkSigNaNs;
82 if ( possibleOppositeZeros && ((mashWord | wordA | wordB) != 0) ) {
83 goto false_checkSigNaNs;
84 }
85 if ( ! softfloat_isNaNF128M( aWPtr ) && ! softfloat_isNaNF128M( bWPtr ) ) {
86 return true;
87 }
88 false_checkSigNaNs:
89 if (
90 f128M_isSignalingNaN( (const float128_t *) aWPtr )
91 || f128M_isSignalingNaN( (const float128_t *) bWPtr )
92 ) {
93 softfloat_raiseFlags( softfloat_flag_invalid );
94 }
95 return false;
96
97}
98
99#endif
100
deps/SoftFloat-3e/source/f128M_eq_signaling.c deleted-92
...@@ -1,92 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46bool f128M_eq_signaling( const float128_t *aPtr, const float128_t *bPtr )
47{
48
49 return f128_eq_signaling( *aPtr, *bPtr );
50
51}
52
53#else
54
55bool f128M_eq_signaling( const float128_t *aPtr, const float128_t *bPtr )
56{
57 const uint32_t *aWPtr, *bWPtr;
58 uint32_t wordA, wordB, uiA96, uiB96;
59 bool possibleOppositeZeros;
60 uint32_t mashWord;
61
62 aWPtr = (const uint32_t *) aPtr;
63 bWPtr = (const uint32_t *) bPtr;
64 if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) {
65 softfloat_raiseFlags( softfloat_flag_invalid );
66 return false;
67 }
68 wordA = aWPtr[indexWord( 4, 2 )];
69 wordB = bWPtr[indexWord( 4, 2 )];
70 if ( wordA != wordB ) return false;
71 uiA96 = aWPtr[indexWordHi( 4 )];
72 uiB96 = bWPtr[indexWordHi( 4 )];
73 possibleOppositeZeros = false;
74 if ( uiA96 != uiB96 ) {
75 possibleOppositeZeros = (((uiA96 | uiB96) & 0x7FFFFFFF) == 0);
76 if ( ! possibleOppositeZeros ) return false;
77 }
78 mashWord = wordA | wordB;
79 wordA = aWPtr[indexWord( 4, 1 )];
80 wordB = bWPtr[indexWord( 4, 1 )];
81 if ( wordA != wordB ) return false;
82 mashWord |= wordA | wordB;
83 wordA = aWPtr[indexWord( 4, 0 )];
84 wordB = bWPtr[indexWord( 4, 0 )];
85 return
86 (wordA == wordB)
87 && (! possibleOppositeZeros || ((mashWord | wordA | wordB) == 0));
88
89}
90
91#endif
92
deps/SoftFloat-3e/source/f128M_le.c deleted-93
...@@ -1,93 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43#ifdef SOFTFLOAT_FAST_INT64
44
45bool f128M_le( const float128_t *aPtr, const float128_t *bPtr )
46{
47
48 return f128_le( *aPtr, *bPtr );
49
50}
51
52#else
53
54bool f128M_le( const float128_t *aPtr, const float128_t *bPtr )
55{
56 const uint32_t *aWPtr, *bWPtr;
57 uint32_t uiA96, uiB96;
58 bool signA, signB;
59 uint32_t wordA, wordB;
60
61 aWPtr = (const uint32_t *) aPtr;
62 bWPtr = (const uint32_t *) bPtr;
63 if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) {
64 softfloat_raiseFlags( softfloat_flag_invalid );
65 return false;
66 }
67 uiA96 = aWPtr[indexWordHi( 4 )];
68 uiB96 = bWPtr[indexWordHi( 4 )];
69 signA = signF128UI96( uiA96 );
70 signB = signF128UI96( uiB96 );
71 if ( signA != signB ) {
72 if ( signA ) return true;
73 if ( (uiA96 | uiB96) & 0x7FFFFFFF ) return false;
74 wordA = aWPtr[indexWord( 4, 2 )];
75 wordB = bWPtr[indexWord( 4, 2 )];
76 if ( wordA | wordB ) return false;
77 wordA = aWPtr[indexWord( 4, 1 )];
78 wordB = bWPtr[indexWord( 4, 1 )];
79 if ( wordA | wordB ) return false;
80 wordA = aWPtr[indexWord( 4, 0 )];
81 wordB = bWPtr[indexWord( 4, 0 )];
82 return ((wordA | wordB) == 0);
83 }
84 if ( signA ) {
85 aWPtr = (const uint32_t *) bPtr;
86 bWPtr = (const uint32_t *) aPtr;
87 }
88 return (softfloat_compare128M( aWPtr, bWPtr ) <= 0);
89
90}
91
92#endif
93
deps/SoftFloat-3e/source/f128M_le_quiet.c deleted-96
...@@ -1,96 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46bool f128M_le_quiet( const float128_t *aPtr, const float128_t *bPtr )
47{
48
49 return f128_le_quiet( *aPtr, *bPtr );
50
51}
52
53#else
54
55bool f128M_le_quiet( const float128_t *aPtr, const float128_t *bPtr )
56{
57 const uint32_t *aWPtr, *bWPtr;
58 uint32_t uiA96, uiB96;
59 bool signA, signB;
60 uint32_t wordA, wordB;
61
62 aWPtr = (const uint32_t *) aPtr;
63 bWPtr = (const uint32_t *) bPtr;
64 if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) {
65 if ( f128M_isSignalingNaN( aPtr ) || f128M_isSignalingNaN( bPtr ) ) {
66 softfloat_raiseFlags( softfloat_flag_invalid );
67 }
68 return false;
69 }
70 uiA96 = aWPtr[indexWordHi( 4 )];
71 uiB96 = bWPtr[indexWordHi( 4 )];
72 signA = signF128UI96( uiA96 );
73 signB = signF128UI96( uiB96 );
74 if ( signA != signB ) {
75 if ( signA ) return true;
76 if ( (uiA96 | uiB96) & 0x7FFFFFFF ) return false;
77 wordA = aWPtr[indexWord( 4, 2 )];
78 wordB = bWPtr[indexWord( 4, 2 )];
79 if ( wordA | wordB ) return false;
80 wordA = aWPtr[indexWord( 4, 1 )];
81 wordB = bWPtr[indexWord( 4, 1 )];
82 if ( wordA | wordB ) return false;
83 wordA = aWPtr[indexWord( 4, 0 )];
84 wordB = bWPtr[indexWord( 4, 0 )];
85 return ((wordA | wordB) == 0);
86 }
87 if ( signA ) {
88 aWPtr = (const uint32_t *) bPtr;
89 bWPtr = (const uint32_t *) aPtr;
90 }
91 return (softfloat_compare128M( aWPtr, bWPtr ) <= 0);
92
93}
94
95#endif
96
deps/SoftFloat-3e/source/f128M_lt.c deleted-93
...@@ -1,93 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43#ifdef SOFTFLOAT_FAST_INT64
44
45bool f128M_lt( const float128_t *aPtr, const float128_t *bPtr )
46{
47
48 return f128_lt( *aPtr, *bPtr );
49
50}
51
52#else
53
54bool f128M_lt( const float128_t *aPtr, const float128_t *bPtr )
55{
56 const uint32_t *aWPtr, *bWPtr;
57 uint32_t uiA96, uiB96;
58 bool signA, signB;
59 uint32_t wordA, wordB;
60
61 aWPtr = (const uint32_t *) aPtr;
62 bWPtr = (const uint32_t *) bPtr;
63 if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) {
64 softfloat_raiseFlags( softfloat_flag_invalid );
65 return false;
66 }
67 uiA96 = aWPtr[indexWordHi( 4 )];
68 uiB96 = bWPtr[indexWordHi( 4 )];
69 signA = signF128UI96( uiA96 );
70 signB = signF128UI96( uiB96 );
71 if ( signA != signB ) {
72 if ( signB ) return false;
73 if ( (uiA96 | uiB96) & 0x7FFFFFFF ) return true;
74 wordA = aWPtr[indexWord( 4, 2 )];
75 wordB = bWPtr[indexWord( 4, 2 )];
76 if ( wordA | wordB ) return true;
77 wordA = aWPtr[indexWord( 4, 1 )];
78 wordB = bWPtr[indexWord( 4, 1 )];
79 if ( wordA | wordB ) return true;
80 wordA = aWPtr[indexWord( 4, 0 )];
81 wordB = bWPtr[indexWord( 4, 0 )];
82 return ((wordA | wordB) != 0);
83 }
84 if ( signA ) {
85 aWPtr = (const uint32_t *) bPtr;
86 bWPtr = (const uint32_t *) aPtr;
87 }
88 return (softfloat_compare128M( aWPtr, bWPtr ) < 0);
89
90}
91
92#endif
93
deps/SoftFloat-3e/source/f128M_lt_quiet.c deleted-96
...@@ -1,96 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46bool f128M_lt_quiet( const float128_t *aPtr, const float128_t *bPtr )
47{
48
49 return f128_lt_quiet( *aPtr, *bPtr );
50
51}
52
53#else
54
55bool f128M_lt_quiet( const float128_t *aPtr, const float128_t *bPtr )
56{
57 const uint32_t *aWPtr, *bWPtr;
58 uint32_t uiA96, uiB96;
59 bool signA, signB;
60 uint32_t wordA, wordB;
61
62 aWPtr = (const uint32_t *) aPtr;
63 bWPtr = (const uint32_t *) bPtr;
64 if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) {
65 if ( f128M_isSignalingNaN( aPtr ) || f128M_isSignalingNaN( bPtr ) ) {
66 softfloat_raiseFlags( softfloat_flag_invalid );
67 }
68 return false;
69 }
70 uiA96 = aWPtr[indexWordHi( 4 )];
71 uiB96 = bWPtr[indexWordHi( 4 )];
72 signA = signF128UI96( uiA96 );
73 signB = signF128UI96( uiB96 );
74 if ( signA != signB ) {
75 if ( signB ) return false;
76 if ( (uiA96 | uiB96) & 0x7FFFFFFF ) return true;
77 wordA = aWPtr[indexWord( 4, 2 )];
78 wordB = bWPtr[indexWord( 4, 2 )];
79 if ( wordA | wordB ) return true;
80 wordA = aWPtr[indexWord( 4, 1 )];
81 wordB = bWPtr[indexWord( 4, 1 )];
82 if ( wordA | wordB ) return true;
83 wordA = aWPtr[indexWord( 4, 0 )];
84 wordB = bWPtr[indexWord( 4, 0 )];
85 return ((wordA | wordB) != 0);
86 }
87 if ( signA ) {
88 aWPtr = (const uint32_t *) bPtr;
89 bWPtr = (const uint32_t *) aPtr;
90 }
91 return (softfloat_compare128M( aWPtr, bWPtr ) < 0);
92
93}
94
95#endif
96
deps/SoftFloat-3e/source/f128M_mul.c deleted-158
...@@ -1,158 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void
47 f128M_mul( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
48{
49
50 *zPtr = f128_mul( *aPtr, *bPtr );
51
52}
53
54#else
55
56void
57 f128M_mul( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
58{
59 const uint32_t *aWPtr, *bWPtr;
60 uint32_t *zWPtr;
61 uint32_t uiA96;
62 int32_t expA;
63 uint32_t uiB96;
64 int32_t expB;
65 bool signZ;
66 const uint32_t *ptr;
67 uint32_t uiZ96, sigA[4];
68 uint_fast8_t shiftDist;
69 uint32_t sigB[4];
70 int32_t expZ;
71 uint32_t sigProd[8], *extSigZPtr;
72
73 /*------------------------------------------------------------------------
74 *------------------------------------------------------------------------*/
75 aWPtr = (const uint32_t *) aPtr;
76 bWPtr = (const uint32_t *) bPtr;
77 zWPtr = (uint32_t *) zPtr;
78 /*------------------------------------------------------------------------
79 *------------------------------------------------------------------------*/
80 uiA96 = aWPtr[indexWordHi( 4 )];
81 expA = expF128UI96( uiA96 );
82 uiB96 = bWPtr[indexWordHi( 4 )];
83 expB = expF128UI96( uiB96 );
84 signZ = signF128UI96( uiA96 ) ^ signF128UI96( uiB96 );
85 /*------------------------------------------------------------------------
86 *------------------------------------------------------------------------*/
87 if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
88 if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return;
89 ptr = aWPtr;
90 if ( ! expA ) goto possiblyInvalid;
91 if ( ! expB ) {
92 ptr = bWPtr;
93 possiblyInvalid:
94 if (
95 ! fracF128UI96( ptr[indexWordHi( 4 )] )
96 && ! (ptr[indexWord( 4, 2 )] | ptr[indexWord( 4, 1 )]
97 | ptr[indexWord( 4, 0 )])
98 ) {
99 softfloat_invalidF128M( zWPtr );
100 return;
101 }
102 }
103 uiZ96 = packToF128UI96( signZ, 0x7FFF, 0 );
104 goto uiZ96;
105 }
106 /*------------------------------------------------------------------------
107 *------------------------------------------------------------------------*/
108 if ( expA ) {
109 sigA[indexWordHi( 4 )] = fracF128UI96( uiA96 ) | 0x00010000;
110 sigA[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )];
111 sigA[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )];
112 sigA[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )];
113 } else {
114 expA = softfloat_shiftNormSigF128M( aWPtr, 0, sigA );
115 if ( expA == -128 ) goto zero;
116 }
117 if ( expB ) {
118 sigB[indexWordHi( 4 )] = fracF128UI96( uiB96 ) | 0x00010000;
119 sigB[indexWord( 4, 2 )] = bWPtr[indexWord( 4, 2 )];
120 sigB[indexWord( 4, 1 )] = bWPtr[indexWord( 4, 1 )];
121 sigB[indexWord( 4, 0 )] = bWPtr[indexWord( 4, 0 )];
122 } else {
123 expB = softfloat_shiftNormSigF128M( bWPtr, 0, sigB );
124 if ( expB == -128 ) goto zero;
125 }
126 /*------------------------------------------------------------------------
127 *------------------------------------------------------------------------*/
128 expZ = expA + expB - 0x4000;
129 softfloat_mul128MTo256M( sigA, sigB, sigProd );
130 if (
131 sigProd[indexWord( 8, 2 )]
132 || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )])
133 ) {
134 sigProd[indexWord( 8, 3 )] |= 1;
135 }
136 extSigZPtr = &sigProd[indexMultiwordHi( 8, 5 )];
137 shiftDist = 16;
138 if ( extSigZPtr[indexWordHi( 5 )] & 2 ) {
139 ++expZ;
140 shiftDist = 15;
141 }
142 softfloat_shortShiftLeft160M( extSigZPtr, shiftDist, extSigZPtr );
143 softfloat_roundPackMToF128M( signZ, expZ, extSigZPtr, zWPtr );
144 return;
145 /*------------------------------------------------------------------------
146 *------------------------------------------------------------------------*/
147 zero:
148 uiZ96 = packToF128UI96( signZ, 0, 0 );
149 uiZ96:
150 zWPtr[indexWordHi( 4 )] = uiZ96;
151 zWPtr[indexWord( 4, 2 )] = 0;
152 zWPtr[indexWord( 4, 1 )] = 0;
153 zWPtr[indexWord( 4, 0 )] = 0;
154
155}
156
157#endif
158
deps/SoftFloat-3e/source/f128M_mulAdd.c deleted-92
...@@ -1,92 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42#ifdef SOFTFLOAT_FAST_INT64
43
44void
45 f128M_mulAdd(
46 const float128_t *aPtr,
47 const float128_t *bPtr,
48 const float128_t *cPtr,
49 float128_t *zPtr
50 )
51{
52 const uint64_t *aWPtr, *bWPtr, *cWPtr;
53 uint_fast64_t uiA64, uiA0;
54 uint_fast64_t uiB64, uiB0;
55 uint_fast64_t uiC64, uiC0;
56
57 aWPtr = (const uint64_t *) aPtr;
58 bWPtr = (const uint64_t *) bPtr;
59 cWPtr = (const uint64_t *) cPtr;
60 uiA64 = aWPtr[indexWord( 2, 1 )];
61 uiA0 = aWPtr[indexWord( 2, 0 )];
62 uiB64 = bWPtr[indexWord( 2, 1 )];
63 uiB0 = bWPtr[indexWord( 2, 0 )];
64 uiC64 = cWPtr[indexWord( 2, 1 )];
65 uiC0 = cWPtr[indexWord( 2, 0 )];
66 *zPtr = softfloat_mulAddF128( uiA64, uiA0, uiB64, uiB0, uiC64, uiC0, 0 );
67
68}
69
70#else
71
72void
73 f128M_mulAdd(
74 const float128_t *aPtr,
75 const float128_t *bPtr,
76 const float128_t *cPtr,
77 float128_t *zPtr
78 )
79{
80
81 softfloat_mulAddF128M(
82 (const uint32_t *) aPtr,
83 (const uint32_t *) bPtr,
84 (const uint32_t *) cPtr,
85 (uint32_t *) zPtr,
86 0
87 );
88
89}
90
91#endif
92
deps/SoftFloat-3e/source/f128M_rem.c deleted-182
...@@ -1,182 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void
47 f128M_rem( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
48{
49
50 *zPtr = f128_rem( *aPtr, *bPtr );
51
52}
53
54#else
55
56void
57 f128M_rem( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
58{
59 const uint32_t *aWPtr, *bWPtr;
60 uint32_t *zWPtr, uiA96;
61 int32_t expA, expB;
62 uint32_t x[4], rem1[5], *remPtr;
63 bool signRem;
64 int32_t expDiff;
65 uint32_t q, recip32;
66 uint64_t q64;
67 uint32_t rem2[5], *altRemPtr, *newRemPtr, wordMeanRem;
68
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 aWPtr = (const uint32_t *) aPtr;
72 bWPtr = (const uint32_t *) bPtr;
73 zWPtr = (uint32_t *) zPtr;
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 uiA96 = aWPtr[indexWordHi( 4 )];
77 expA = expF128UI96( uiA96 );
78 expB = expF128UI96( bWPtr[indexWordHi( 4 )] );
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
82 if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return;
83 if ( expA == 0x7FFF ) goto invalid;
84 goto copyA;
85 }
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 if ( expA < expB - 1 ) goto copyA;
89 /*------------------------------------------------------------------------
90 *------------------------------------------------------------------------*/
91 expB = softfloat_shiftNormSigF128M( bWPtr, 13, x );
92 if ( expB == -128 ) goto invalid;
93 remPtr = &rem1[indexMultiwordLo( 5, 4 )];
94 expA = softfloat_shiftNormSigF128M( aWPtr, 13, remPtr );
95 if ( expA == -128 ) goto copyA;
96 signRem = signF128UI96( uiA96 );
97 /*------------------------------------------------------------------------
98 *------------------------------------------------------------------------*/
99 expDiff = expA - expB;
100 if ( expDiff < 1 ) {
101 if ( expDiff < -1 ) goto copyA;
102 if ( expDiff ) {
103 --expB;
104 softfloat_add128M( x, x, x );
105 q = 0;
106 } else {
107 q = (softfloat_compare128M( x, remPtr ) <= 0);
108 if ( q ) softfloat_sub128M( remPtr, x, remPtr );
109 }
110 } else {
111 recip32 =
112 softfloat_approxRecip32_1(
113 ((uint64_t) x[indexWord( 4, 3 )]<<32 | x[indexWord( 4, 2 )])
114 >>30
115 );
116 expDiff -= 30;
117 for (;;) {
118 q64 = (uint64_t) remPtr[indexWordHi( 4 )] * recip32;
119 if ( expDiff < 0 ) break;
120 q = (q64 + 0x80000000)>>32;
121 softfloat_remStep128MBy32( remPtr, 29, x, q, remPtr );
122 if ( remPtr[indexWordHi( 4 )] & 0x80000000 ) {
123 softfloat_add128M( remPtr, x, remPtr );
124 }
125 expDiff -= 29;
126 }
127 /*--------------------------------------------------------------------
128 | (`expDiff' cannot be less than -29 here.)
129 *--------------------------------------------------------------------*/
130 q = (uint32_t) (q64>>32)>>(~expDiff & 31);
131 softfloat_remStep128MBy32( remPtr, expDiff + 30, x, q, remPtr );
132 if ( remPtr[indexWordHi( 4 )] & 0x80000000 ) {
133 altRemPtr = &rem2[indexMultiwordLo( 5, 4 )];
134 softfloat_add128M( remPtr, x, altRemPtr );
135 goto selectRem;
136 }
137 }
138 /*------------------------------------------------------------------------
139 *------------------------------------------------------------------------*/
140 altRemPtr = &rem2[indexMultiwordLo( 5, 4 )];
141 do {
142 ++q;
143 newRemPtr = altRemPtr;
144 softfloat_sub128M( remPtr, x, newRemPtr );
145 altRemPtr = remPtr;
146 remPtr = newRemPtr;
147 } while ( ! (remPtr[indexWordHi( 4 )] & 0x80000000) );
148 selectRem:
149 softfloat_add128M( remPtr, altRemPtr, x );
150 wordMeanRem = x[indexWordHi( 4 )];
151 if (
152 (wordMeanRem & 0x80000000)
153 || (! wordMeanRem && (q & 1) && ! x[indexWord( 4, 0 )]
154 && ! (x[indexWord( 4, 2 )] | x[indexWord( 4, 1 )]))
155 ) {
156 remPtr = altRemPtr;
157 }
158 if ( remPtr[indexWordHi( 4 )] & 0x80000000 ) {
159 signRem = ! signRem;
160 softfloat_negX128M( remPtr );
161 }
162 remPtr -= indexMultiwordLo( 5, 4 );
163 remPtr[indexWordHi( 5 )] = 0;
164 softfloat_normRoundPackMToF128M( signRem, expB + 18, remPtr, zWPtr );
165 return;
166 /*------------------------------------------------------------------------
167 *------------------------------------------------------------------------*/
168 invalid:
169 softfloat_invalidF128M( zWPtr );
170 return;
171 /*------------------------------------------------------------------------
172 *------------------------------------------------------------------------*/
173 copyA:
174 zWPtr[indexWordHi( 4 )] = uiA96;
175 zWPtr[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )];
176 zWPtr[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )];
177 zWPtr[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )];
178
179}
180
181#endif
182
deps/SoftFloat-3e/source/f128M_roundToInt.c deleted-223
...@@ -1,223 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void
47 f128M_roundToInt(
48 const float128_t *aPtr,
49 uint_fast8_t roundingMode,
50 bool exact,
51 float128_t *zPtr
52 )
53{
54
55 *zPtr = f128_roundToInt( *aPtr, roundingMode, exact );
56
57}
58
59#else
60
61void
62 f128M_roundToInt(
63 const float128_t *aPtr,
64 uint_fast8_t roundingMode,
65 bool exact,
66 float128_t *zPtr
67 )
68{
69 const uint32_t *aWPtr;
70 uint32_t *zWPtr;
71 uint32_t ui96;
72 int32_t exp;
73 uint32_t sigExtra;
74 bool sign;
75 uint_fast8_t bitPos;
76 bool roundNear;
77 unsigned int index, lastIndex;
78 bool extra;
79 uint32_t wordA, bit, wordZ;
80 uint_fast8_t carry;
81 uint32_t extrasMask;
82
83 /*------------------------------------------------------------------------
84 *------------------------------------------------------------------------*/
85 aWPtr = (const uint32_t *) aPtr;
86 zWPtr = (uint32_t *) zPtr;
87 /*------------------------------------------------------------------------
88 *------------------------------------------------------------------------*/
89 ui96 = aWPtr[indexWordHi( 4 )];
90 exp = expF128UI96( ui96 );
91 /*------------------------------------------------------------------------
92 *------------------------------------------------------------------------*/
93 if ( exp < 0x3FFF ) {
94 zWPtr[indexWord( 4, 2 )] = 0;
95 zWPtr[indexWord( 4, 1 )] = 0;
96 zWPtr[indexWord( 4, 0 )] = 0;
97 sigExtra = aWPtr[indexWord( 4, 2 )];
98 if ( !sigExtra ) {
99 sigExtra = aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )];
100 }
101 if ( !sigExtra && !(ui96 & 0x7FFFFFFF) ) goto ui96;
102 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
103 sign = signF128UI96( ui96 );
104 switch ( roundingMode ) {
105 case softfloat_round_near_even:
106 if ( !fracF128UI96( ui96 ) && !sigExtra ) break;
107 case softfloat_round_near_maxMag:
108 if ( exp == 0x3FFE ) goto mag1;
109 break;
110 case softfloat_round_min:
111 if ( sign ) goto mag1;
112 break;
113 case softfloat_round_max:
114 if ( !sign ) goto mag1;
115 break;
116#ifdef SOFTFLOAT_ROUND_ODD
117 case softfloat_round_odd:
118 goto mag1;
119#endif
120 }
121 ui96 = packToF128UI96( sign, 0, 0 );
122 goto ui96;
123 mag1:
124 ui96 = packToF128UI96( sign, 0x3FFF, 0 );
125 goto ui96;
126 }
127 /*------------------------------------------------------------------------
128 *------------------------------------------------------------------------*/
129 if ( 0x406F <= exp ) {
130 if (
131 (exp == 0x7FFF)
132 && (fracF128UI96( ui96 )
133 || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
134 | aWPtr[indexWord( 4, 0 )]))
135 ) {
136 softfloat_propagateNaNF128M( aWPtr, 0, zWPtr );
137 return;
138 }
139 zWPtr[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )];
140 zWPtr[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )];
141 zWPtr[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )];
142 goto ui96;
143 }
144 /*------------------------------------------------------------------------
145 *------------------------------------------------------------------------*/
146 bitPos = 0x406F - exp;
147 roundNear =
148 (roundingMode == softfloat_round_near_maxMag)
149 || (roundingMode == softfloat_round_near_even);
150 bitPos -= roundNear;
151 index = indexWordLo( 4 );
152 lastIndex = indexWordHi( 4 );
153 extra = 0;
154 for (;;) {
155 wordA = aWPtr[index];
156 if ( bitPos < 32 ) break;
157 if ( wordA ) extra = 1;
158 zWPtr[index] = 0;
159 index += wordIncr;
160 bitPos -= 32;
161 }
162 bit = (uint32_t) 1<<bitPos;
163 if ( roundNear ) {
164 wordZ = wordA + bit;
165 carry = (wordZ < wordA);
166 bit <<= 1;
167 extrasMask = bit - 1;
168 if ( exact && (extra || (wordA & extrasMask)) ) {
169 softfloat_exceptionFlags |= softfloat_flag_inexact;
170 }
171 if (
172 (roundingMode == softfloat_round_near_even)
173 && !extra && !(wordZ & extrasMask)
174 ) {
175 if ( !bit ) {
176 zWPtr[index] = wordZ;
177 index += wordIncr;
178 wordZ = aWPtr[index] + carry;
179 carry &= !wordZ;
180 zWPtr[index] = wordZ & ~1;
181 goto propagateCarry;
182 }
183 wordZ &= ~bit;
184 }
185 } else {
186 wordZ = wordA;
187 carry = 0;
188 extrasMask = bit - 1;
189 if ( extra || (wordA & extrasMask) ) {
190 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
191 if (
192 roundingMode
193 == (signF128UI96( ui96 ) ? softfloat_round_min
194 : softfloat_round_max)
195 ) {
196 wordZ += bit;
197 carry = (wordZ < wordA);
198#ifdef SOFTFLOAT_ROUND_ODD
199 } else if ( roundingMode == softfloat_round_odd ) {
200 wordZ |= bit;
201#endif
202 }
203 }
204 }
205 wordZ &= ~extrasMask;
206 zWPtr[index] = wordZ;
207 propagateCarry:
208 while ( index != lastIndex ) {
209 index += wordIncr;
210 wordZ = aWPtr[index] + carry;
211 zWPtr[index] = wordZ;
212 carry &= !wordZ;
213 }
214 return;
215 /*------------------------------------------------------------------------
216 *------------------------------------------------------------------------*/
217 ui96:
218 zWPtr[indexWordHi( 4 )] = ui96;
219
220}
221
222#endif
223
deps/SoftFloat-3e/source/f128M_sqrt.c deleted-228
...@@ -1,228 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void f128M_sqrt( const float128_t *aPtr, float128_t *zPtr )
47{
48
49 *zPtr = f128_sqrt( *aPtr );
50
51}
52
53#else
54
55void f128M_sqrt( const float128_t *aPtr, float128_t *zPtr )
56{
57 const uint32_t *aWPtr;
58 uint32_t *zWPtr;
59 uint32_t uiA96;
60 bool signA;
61 int32_t rawExpA;
62 uint32_t rem[6];
63 int32_t expA, expZ;
64 uint64_t rem64;
65 uint32_t sig32A, recipSqrt32, sig32Z, qs[3], q;
66 uint64_t sig64Z;
67 uint32_t term[5];
68 uint64_t x64;
69 uint32_t y[5], rem32;
70
71 /*------------------------------------------------------------------------
72 *------------------------------------------------------------------------*/
73 aWPtr = (const uint32_t *) aPtr;
74 zWPtr = (uint32_t *) zPtr;
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 uiA96 = aWPtr[indexWordHi( 4 )];
78 signA = signF128UI96( uiA96 );
79 rawExpA = expF128UI96( uiA96 );
80 /*------------------------------------------------------------------------
81 *------------------------------------------------------------------------*/
82 if ( rawExpA == 0x7FFF ) {
83 if (
84 fracF128UI96( uiA96 )
85 || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
86 | aWPtr[indexWord( 4, 0 )])
87 ) {
88 softfloat_propagateNaNF128M( aWPtr, 0, zWPtr );
89 return;
90 }
91 if ( ! signA ) goto copyA;
92 goto invalid;
93 }
94 /*------------------------------------------------------------------------
95 *------------------------------------------------------------------------*/
96 expA = softfloat_shiftNormSigF128M( aWPtr, 13 - (rawExpA & 1), rem );
97 if ( expA == -128 ) goto copyA;
98 if ( signA ) goto invalid;
99 /*------------------------------------------------------------------------
100 | (`sig32Z' is guaranteed to be a lower bound on the square root of
101 | `sig32A', which makes `sig32Z' also a lower bound on the square root of
102 | `sigA'.)
103 *------------------------------------------------------------------------*/
104 expZ = ((expA - 0x3FFF)>>1) + 0x3FFE;
105 expA &= 1;
106 rem64 = (uint64_t) rem[indexWord( 4, 3 )]<<32 | rem[indexWord( 4, 2 )];
107 if ( expA ) {
108 if ( ! rawExpA ) {
109 softfloat_shortShiftRight128M( rem, 1, rem );
110 rem64 >>= 1;
111 }
112 sig32A = rem64>>29;
113 } else {
114 sig32A = rem64>>30;
115 }
116 recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A );
117 sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32;
118 if ( expA ) sig32Z >>= 1;
119 qs[2] = sig32Z;
120 rem64 -= (uint64_t) sig32Z * sig32Z;
121 rem[indexWord( 4, 3 )] = rem64>>32;
122 rem[indexWord( 4, 2 )] = rem64;
123 /*------------------------------------------------------------------------
124 *------------------------------------------------------------------------*/
125 q = ((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32;
126 sig64Z = ((uint64_t) sig32Z<<32) + ((uint64_t) q<<3);
127 term[indexWord( 4, 3 )] = 0;
128 term[indexWord( 4, 0 )] = 0;
129 /*------------------------------------------------------------------------
130 | (Repeating this loop is a rare occurrence.)
131 *------------------------------------------------------------------------*/
132 for (;;) {
133 x64 = ((uint64_t) sig32Z<<32) + sig64Z;
134 term[indexWord( 4, 2 )] = x64>>32;
135 term[indexWord( 4, 1 )] = x64;
136 softfloat_remStep128MBy32( rem, 29, term, q, y );
137 rem32 = y[indexWord( 4, 3 )];
138 if ( ! (rem32 & 0x80000000) ) break;
139 --q;
140 sig64Z -= 1<<3;
141 }
142 qs[1] = q;
143 rem64 = (uint64_t) rem32<<32 | y[indexWord( 4, 2 )];
144 /*------------------------------------------------------------------------
145 *------------------------------------------------------------------------*/
146 q = ((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32;
147 if ( rem64>>34 ) q += recipSqrt32;
148 sig64Z <<= 1;
149 /*------------------------------------------------------------------------
150 | (Repeating this loop is a rare occurrence.)
151 *------------------------------------------------------------------------*/
152 for (;;) {
153 x64 = sig64Z + (q>>26);
154 term[indexWord( 4, 2 )] = x64>>32;
155 term[indexWord( 4, 1 )] = x64;
156 term[indexWord( 4, 0 )] = q<<6;
157 softfloat_remStep128MBy32(
158 y, 29, term, q, &rem[indexMultiwordHi( 6, 4 )] );
159 rem32 = rem[indexWordHi( 6 )];
160 if ( ! (rem32 & 0x80000000) ) break;
161 --q;
162 }
163 qs[0] = q;
164 rem64 = (uint64_t) rem32<<32 | rem[indexWord( 6, 4 )];
165 /*------------------------------------------------------------------------
166 *------------------------------------------------------------------------*/
167 q = (((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32) + 2;
168 if ( rem64>>34 ) q += recipSqrt32;
169 x64 = (uint64_t) q<<27;
170 y[indexWord( 5, 0 )] = x64;
171 x64 = ((uint64_t) qs[0]<<24) + (x64>>32);
172 y[indexWord( 5, 1 )] = x64;
173 x64 = ((uint64_t) qs[1]<<21) + (x64>>32);
174 y[indexWord( 5, 2 )] = x64;
175 x64 = ((uint64_t) qs[2]<<18) + (x64>>32);
176 y[indexWord( 5, 3 )] = x64;
177 y[indexWord( 5, 4 )] = x64>>32;
178 /*------------------------------------------------------------------------
179 *------------------------------------------------------------------------*/
180 if ( (q & 0xF) <= 2 ) {
181 q &= ~3;
182 y[indexWordLo( 5 )] = q<<27;
183 term[indexWord( 5, 4 )] = 0;
184 term[indexWord( 5, 3 )] = 0;
185 term[indexWord( 5, 2 )] = 0;
186 term[indexWord( 5, 1 )] = q>>6;
187 term[indexWord( 5, 0 )] = q<<26;
188 softfloat_sub160M( y, term, term );
189 rem[indexWord( 6, 1 )] = 0;
190 rem[indexWord( 6, 0 )] = 0;
191 softfloat_remStep160MBy32(
192 &rem[indexMultiwordLo( 6, 5 )],
193 14,
194 term,
195 q,
196 &rem[indexMultiwordLo( 6, 5 )]
197 );
198 rem32 = rem[indexWord( 6, 4 )];
199 if ( rem32 & 0x80000000 ) {
200 softfloat_sub1X160M( y );
201 } else {
202 if (
203 rem32 || rem[indexWord( 6, 0 )] || rem[indexWord( 6, 1 )]
204 || (rem[indexWord( 6, 3 )] | rem[indexWord( 6, 2 )])
205 ) {
206 y[indexWordLo( 5 )] |= 1;
207 }
208 }
209 }
210 softfloat_roundPackMToF128M( 0, expZ, y, zWPtr );
211 return;
212 /*------------------------------------------------------------------------
213 *------------------------------------------------------------------------*/
214 invalid:
215 softfloat_invalidF128M( zWPtr );
216 return;
217 /*------------------------------------------------------------------------
218 *------------------------------------------------------------------------*/
219 copyA:
220 zWPtr[indexWordHi( 4 )] = uiA96;
221 zWPtr[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )];
222 zWPtr[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )];
223 zWPtr[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )];
224
225}
226
227#endif
228
deps/SoftFloat-3e/source/f128M_sub.c deleted-97
...@@ -1,97 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43#ifdef SOFTFLOAT_FAST_INT64
44
45void
46 f128M_sub( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
47{
48 const uint64_t *aWPtr, *bWPtr;
49 uint_fast64_t uiA64, uiA0;
50 bool signA;
51 uint_fast64_t uiB64, uiB0;
52 bool signB;
53#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
54 float128_t
55 (*magsFuncPtr)(
56 uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
57#endif
58
59 aWPtr = (const uint64_t *) aPtr;
60 bWPtr = (const uint64_t *) bPtr;
61 uiA64 = aWPtr[indexWord( 2, 1 )];
62 uiA0 = aWPtr[indexWord( 2, 0 )];
63 signA = signF128UI64( uiA64 );
64 uiB64 = bWPtr[indexWord( 2, 1 )];
65 uiB0 = bWPtr[indexWord( 2, 0 )];
66 signB = signF128UI64( uiB64 );
67#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
68 if ( signA == signB ) {
69 *zPtr = softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
70 } else {
71 *zPtr = softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
72 }
73#else
74 magsFuncPtr =
75 (signA == signB) ? softfloat_subMagsF128 : softfloat_addMagsF128;
76 *zPtr = (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
77#endif
78
79}
80
81#else
82
83void
84 f128M_sub( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
85{
86
87 softfloat_addF128M(
88 (const uint32_t *) aPtr,
89 (const uint32_t *) bPtr,
90 (uint32_t *) zPtr,
91 true
92 );
93
94}
95
96#endif
97
deps/SoftFloat-3e/source/f128M_to_extF80M.c deleted-101
...@@ -1,101 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void f128M_to_extF80M( const float128_t *aPtr, extFloat80_t *zPtr )
47{
48
49 *zPtr = f128_to_extF80( *aPtr );
50
51}
52
53#else
54
55void f128M_to_extF80M( const float128_t *aPtr, extFloat80_t *zPtr )
56{
57 const uint32_t *aWPtr;
58 struct extFloat80M *zSPtr;
59 uint32_t uiA96;
60 bool sign;
61 int32_t exp;
62 struct commonNaN commonNaN;
63 uint32_t sig[4];
64
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 aWPtr = (const uint32_t *) aPtr;
68 zSPtr = (struct extFloat80M *) zPtr;
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 uiA96 = aWPtr[indexWordHi( 4 )];
72 sign = signF128UI96( uiA96 );
73 exp = expF128UI96( uiA96 );
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( exp == 0x7FFF ) {
77 if ( softfloat_isNaNF128M( aWPtr ) ) {
78 softfloat_f128MToCommonNaN( aWPtr, &commonNaN );
79 softfloat_commonNaNToExtF80M( &commonNaN, zSPtr );
80 return;
81 }
82 zSPtr->signExp = packToExtF80UI64( sign, 0x7FFF );
83 zSPtr->signif = UINT64_C( 0x8000000000000000 );
84 return;
85 }
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 exp = softfloat_shiftNormSigF128M( aWPtr, 15, sig );
89 if ( exp == -128 ) {
90 zSPtr->signExp = packToExtF80UI64( sign, 0 );
91 zSPtr->signif = 0;
92 return;
93 }
94 if ( sig[indexWord( 4, 0 )] ) sig[indexWord( 4, 1 )] |= 1;
95 softfloat_roundPackMToExtF80M(
96 sign, exp, &sig[indexMultiwordHi( 4, 3 )], 80, zSPtr );
97
98}
99
100#endif
101
deps/SoftFloat-3e/source/f128M_to_f16.c deleted-113
...@@ -1,113 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46float16_t f128M_to_f16( const float128_t *aPtr )
47{
48
49 return f128_to_f16( *aPtr );
50
51}
52
53#else
54
55float16_t f128M_to_f16( const float128_t *aPtr )
56{
57 const uint32_t *aWPtr;
58 uint32_t uiA96;
59 bool sign;
60 int32_t exp;
61 uint32_t frac32;
62 struct commonNaN commonNaN;
63 uint16_t uiZ, frac16;
64 union ui16_f16 uZ;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 aWPtr = (const uint32_t *) aPtr;
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 uiA96 = aWPtr[indexWordHi( 4 )];
72 sign = signF128UI96( uiA96 );
73 exp = expF128UI96( uiA96 );
74 frac32 =
75 fracF128UI96( uiA96 )
76 | ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
77 | aWPtr[indexWord( 4, 0 )])
78 != 0);
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 if ( exp == 0x7FFF ) {
82 if ( frac32 ) {
83 softfloat_f128MToCommonNaN( aWPtr, &commonNaN );
84 uiZ = softfloat_commonNaNToF16UI( &commonNaN );
85 } else {
86 uiZ = packToF16UI( sign, 0x1F, 0 );
87 }
88 goto uiZ;
89 }
90 /*------------------------------------------------------------------------
91 *------------------------------------------------------------------------*/
92 frac16 = frac32>>2 | (frac32 & 3);
93 if ( ! (exp | frac16) ) {
94 uiZ = packToF16UI( sign, 0, 0 );
95 goto uiZ;
96 }
97 /*------------------------------------------------------------------------
98 *------------------------------------------------------------------------*/
99 exp -= 0x3FF1;
100 if ( sizeof (int_fast16_t) < sizeof (int32_t) ) {
101 if ( exp < -0x40 ) exp = -0x40;
102 }
103 return softfloat_roundPackToF16( sign, exp, frac16 | 0x4000 );
104 /*------------------------------------------------------------------------
105 *------------------------------------------------------------------------*/
106 uiZ:
107 uZ.ui = uiZ;
108 return uZ.f;
109
110}
111
112#endif
113
deps/SoftFloat-3e/source/f128M_to_f32.c deleted-109
...@@ -1,109 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46float32_t f128M_to_f32( const float128_t *aPtr )
47{
48
49 return f128_to_f32( *aPtr );
50
51}
52
53#else
54
55float32_t f128M_to_f32( const float128_t *aPtr )
56{
57 const uint32_t *aWPtr;
58 uint32_t uiA96;
59 bool sign;
60 int32_t exp;
61 uint64_t frac64;
62 struct commonNaN commonNaN;
63 uint32_t uiZ, frac32;
64 union ui32_f32 uZ;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 aWPtr = (const uint32_t *) aPtr;
69 uiA96 = aWPtr[indexWordHi( 4 )];
70 sign = signF128UI96( uiA96 );
71 exp = expF128UI96( uiA96 );
72 frac64 =
73 (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )]
74 | ((aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]) != 0);
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 if ( exp == 0x7FFF ) {
78 if ( frac64 ) {
79 softfloat_f128MToCommonNaN( aWPtr, &commonNaN );
80 uiZ = softfloat_commonNaNToF32UI( &commonNaN );
81 } else {
82 uiZ = packToF32UI( sign, 0xFF, 0 );
83 }
84 goto uiZ;
85 }
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 frac32 = softfloat_shortShiftRightJam64( frac64, 18 );
89 if ( ! (exp | frac32) ) {
90 uiZ = packToF32UI( sign, 0, 0 );
91 goto uiZ;
92 }
93 /*------------------------------------------------------------------------
94 *------------------------------------------------------------------------*/
95 exp -= 0x3F81;
96 if ( sizeof (int_fast16_t) < sizeof (int32_t) ) {
97 if ( exp < -0x1000 ) exp = -0x1000;
98 }
99 return softfloat_roundPackToF32( sign, exp, frac32 | 0x40000000 );
100 /*------------------------------------------------------------------------
101 *------------------------------------------------------------------------*/
102 uiZ:
103 uZ.ui = uiZ;
104 return uZ.f;
105
106}
107
108#endif
109
deps/SoftFloat-3e/source/f128M_to_f64.c deleted-112
...@@ -1,112 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46float64_t f128M_to_f64( const float128_t *aPtr )
47{
48
49 return f128_to_f64( *aPtr );
50
51}
52
53#else
54
55float64_t f128M_to_f64( const float128_t *aPtr )
56{
57 const uint32_t *aWPtr;
58 uint32_t uiA96;
59 bool sign;
60 int32_t exp;
61 uint64_t frac64;
62 struct commonNaN commonNaN;
63 uint64_t uiZ;
64 uint32_t frac32;
65 union ui64_f64 uZ;
66
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 aWPtr = (const uint32_t *) aPtr;
70 uiA96 = aWPtr[indexWordHi( 4 )];
71 sign = signF128UI96( uiA96 );
72 exp = expF128UI96( uiA96 );
73 frac64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )];
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( exp == 0x7FFF ) {
77 if ( frac64 || aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) {
78 softfloat_f128MToCommonNaN( aWPtr, &commonNaN );
79 uiZ = softfloat_commonNaNToF64UI( &commonNaN );
80 } else {
81 uiZ = packToF64UI( sign, 0x7FF, 0 );
82 }
83 goto uiZ;
84 }
85 /*------------------------------------------------------------------------
86 *------------------------------------------------------------------------*/
87 frac32 = aWPtr[indexWord( 4, 1 )];
88 frac64 = frac64<<14 | frac32>>18;
89 if ( (frac32 & 0x0003FFFF) || aWPtr[indexWord( 4, 0 )] ) frac64 |= 1;
90 if ( ! (exp | frac64) ) {
91 uiZ = packToF64UI( sign, 0, 0 );
92 goto uiZ;
93 }
94 /*------------------------------------------------------------------------
95 *------------------------------------------------------------------------*/
96 exp -= 0x3C01;
97 if ( sizeof (int_fast16_t) < sizeof (int32_t) ) {
98 if ( exp < -0x1000 ) exp = -0x1000;
99 }
100 return
101 softfloat_roundPackToF64(
102 sign, exp, frac64 | UINT64_C( 0x4000000000000000 ) );
103 /*------------------------------------------------------------------------
104 *------------------------------------------------------------------------*/
105 uiZ:
106 uZ.ui = uiZ;
107 return uZ.f;
108
109}
110
111#endif
112
deps/SoftFloat-3e/source/f128M_to_i32.c deleted-98
...@@ -1,98 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46int_fast32_t
47 f128M_to_i32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact )
48{
49
50 return f128_to_i32( *aPtr, roundingMode, exact );
51
52}
53
54#else
55
56int_fast32_t
57 f128M_to_i32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact )
58{
59 const uint32_t *aWPtr;
60 uint32_t uiA96;
61 bool sign;
62 int32_t exp;
63 uint64_t sig64;
64 int32_t shiftDist;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 aWPtr = (const uint32_t *) aPtr;
69 uiA96 = aWPtr[indexWordHi( 4 )];
70 sign = signF128UI96( uiA96 );
71 exp = expF128UI96( uiA96 );
72 sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )];
73 if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) sig64 |= 1;
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
77 if ( (exp == 0x7FFF) && sig64 ) {
78#if (i32_fromNaN == i32_fromPosOverflow)
79 sign = 0;
80#elif (i32_fromNaN == i32_fromNegOverflow)
81 sign = 1;
82#else
83 softfloat_raiseFlags( softfloat_flag_invalid );
84 return i32_fromNaN;
85#endif
86 }
87#endif
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
91 shiftDist = 0x4023 - exp;
92 if ( 0 < shiftDist ) sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
93 return softfloat_roundToI32( sign, sig64, roundingMode, exact );
94
95}
96
97#endif
98
deps/SoftFloat-3e/source/f128M_to_i32_r_minMag.c deleted-106
...@@ -1,106 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46int_fast32_t f128M_to_i32_r_minMag( const float128_t *aPtr, bool exact )
47{
48
49 return f128_to_i32_r_minMag( *aPtr, exact );
50
51}
52
53#else
54
55int_fast32_t f128M_to_i32_r_minMag( const float128_t *aPtr, bool exact )
56{
57 const uint32_t *aWPtr;
58 uint32_t uiA96;
59 bool sign;
60 int32_t exp;
61 uint64_t sig64;
62 int32_t shiftDist;
63 uint32_t absZ, uiZ;
64 union { uint32_t ui; int32_t i; } uZ;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 aWPtr = (const uint32_t *) aPtr;
69 uiA96 = aWPtr[indexWordHi( 4 )];
70 sign = signF128UI96( uiA96 );
71 exp = expF128UI96( uiA96 );
72 sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )];
73 if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) sig64 |= 1;
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( exp < 0x3FFF ) {
77 if ( exact && (exp | sig64) ) {
78 softfloat_exceptionFlags |= softfloat_flag_inexact;
79 }
80 return 0;
81 }
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( 0x401F <= exp ) goto invalid;
85 shiftDist = 0x402F - exp;
86 sig64 |= UINT64_C( 0x0001000000000000 );
87 absZ = sig64>>shiftDist;
88 uiZ = sign ? -absZ : absZ;
89 if ( uiZ>>31 != sign ) goto invalid;
90 if ( exact && ((uint64_t) absZ<<shiftDist != sig64) ) {
91 softfloat_exceptionFlags |= softfloat_flag_inexact;
92 }
93 uZ.ui = uiZ;
94 return uZ.i;
95 /*------------------------------------------------------------------------
96 *------------------------------------------------------------------------*/
97 invalid:
98 softfloat_raiseFlags( softfloat_flag_invalid );
99 return
100 (exp == 0x7FFF) && sig64 ? i32_fromNaN
101 : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
102
103}
104
105#endif
106
deps/SoftFloat-3e/source/f128M_to_i64.c deleted-102
...@@ -1,102 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46int_fast64_t
47 f128M_to_i64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact )
48{
49
50 return f128_to_i64( *aPtr, roundingMode, exact );
51
52}
53
54#else
55
56int_fast64_t
57 f128M_to_i64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact )
58{
59 const uint32_t *aWPtr;
60 uint32_t uiA96;
61 bool sign;
62 int32_t exp;
63 uint32_t sig96;
64 int32_t shiftDist;
65 uint32_t sig[4];
66
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 aWPtr = (const uint32_t *) aPtr;
70 uiA96 = aWPtr[indexWordHi( 4 )];
71 sign = signF128UI96( uiA96 );
72 exp = expF128UI96( uiA96 );
73 sig96 = fracF128UI96( uiA96 );
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 shiftDist = 0x404F - exp;
77 if ( shiftDist < 17 ) {
78 softfloat_raiseFlags( softfloat_flag_invalid );
79 return
80 (exp == 0x7FFF)
81 && (sig96
82 || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
83 | aWPtr[indexWord( 4, 0 )]))
84 ? i64_fromNaN
85 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
86 }
87 /*------------------------------------------------------------------------
88 *------------------------------------------------------------------------*/
89 if ( exp ) sig96 |= 0x00010000;
90 sig[indexWord( 4, 3 )] = sig96;
91 sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )];
92 sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )];
93 sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )];
94 softfloat_shiftRightJam128M( sig, shiftDist, sig );
95 return
96 softfloat_roundMToI64(
97 sign, sig + indexMultiwordLo( 4, 3 ), roundingMode, exact );
98
99}
100
101#endif
102
deps/SoftFloat-3e/source/f128M_to_i64_r_minMag.c deleted-124
...@@ -1,124 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46int_fast64_t f128M_to_i64_r_minMag( const float128_t *aPtr, bool exact )
47{
48
49 return f128_to_i64_r_minMag( *aPtr, exact );
50
51}
52
53#else
54
55int_fast64_t f128M_to_i64_r_minMag( const float128_t *aPtr, bool exact )
56{
57 const uint32_t *aWPtr;
58 uint32_t uiA96;
59 bool sign;
60 int32_t exp;
61 uint32_t sig96;
62 int32_t shiftDist;
63 uint32_t sig[4];
64 uint64_t uiZ;
65 union { uint64_t ui; int64_t i; } uZ;
66
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 aWPtr = (const uint32_t *) aPtr;
70 uiA96 = aWPtr[indexWordHi( 4 )];
71 sign = signF128UI96( uiA96 );
72 exp = expF128UI96( uiA96 );
73 sig96 = fracF128UI96( uiA96 );
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 shiftDist = 0x403E - exp;
77 if ( shiftDist < 0 ) goto invalid;
78 if ( exact ) {
79 if ( exp ) sig96 |= 0x00010000;
80 sig[indexWord( 4, 3 )] = sig96;
81 sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )];
82 sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )];
83 sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )];
84 softfloat_shiftRightJam128M( sig, shiftDist + 17, sig );
85 uiZ = (uint64_t) sig[indexWord( 4, 2 )]<<32 | sig[indexWord( 4, 1 )];
86 if ( uiZ>>63 && (! sign || (uiZ != UINT64_C( 0x8000000000000000 ))) ) {
87 goto invalid;
88 }
89 if ( sig[indexWordLo( 4 )] ) {
90 softfloat_exceptionFlags |= softfloat_flag_inexact;
91 }
92 } else {
93 if ( 64 <= shiftDist ) return 0;
94 uiZ =
95 (uint64_t) sig96<<47
96 | (uint64_t) aWPtr[indexWord( 4, 2 )]<<15
97 | aWPtr[indexWord( 4, 1 )]>>17;
98 if ( shiftDist ) {
99 uiZ |= UINT64_C( 0x8000000000000000 );
100 uiZ >>= shiftDist;
101 } else {
102 if ( uiZ || ! sign ) goto invalid;
103 uiZ |= UINT64_C( 0x8000000000000000 );
104 }
105 }
106 if ( sign ) uiZ = -uiZ;
107 uZ.ui = uiZ;
108 return uZ.i;
109 /*------------------------------------------------------------------------
110 *------------------------------------------------------------------------*/
111 invalid:
112 softfloat_raiseFlags( softfloat_flag_invalid );
113 return
114 (exp == 0x7FFF)
115 && (sig96
116 || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
117 | aWPtr[indexWord( 4, 0 )]))
118 ? i64_fromNaN
119 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
120
121}
122
123#endif
124
deps/SoftFloat-3e/source/f128M_to_ui32.c deleted-98
...@@ -1,98 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46uint_fast32_t
47 f128M_to_ui32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact )
48{
49
50 return f128_to_ui32( *aPtr, roundingMode, exact );
51
52}
53
54#else
55
56uint_fast32_t
57 f128M_to_ui32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact )
58{
59 const uint32_t *aWPtr;
60 uint32_t uiA96;
61 bool sign;
62 int32_t exp;
63 uint64_t sig64;
64 int32_t shiftDist;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 aWPtr = (const uint32_t *) aPtr;
69 uiA96 = aWPtr[indexWordHi( 4 )];
70 sign = signF128UI96( uiA96 );
71 exp = expF128UI96( uiA96 );
72 sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )];
73 if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) sig64 |= 1;
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
77 if ( (exp == 0x7FFF) && sig64 ) {
78#if (ui32_fromNaN == ui32_fromPosOverflow)
79 sign = 0;
80#elif (ui32_fromNaN == ui32_fromNegOverflow)
81 sign = 1;
82#else
83 softfloat_raiseFlags( softfloat_flag_invalid );
84 return ui32_fromNaN;
85#endif
86 }
87#endif
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
91 shiftDist = 0x4023 - exp;
92 if ( 0 < shiftDist ) sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
93 return softfloat_roundToUI32( sign, sig64, roundingMode, exact );
94
95}
96
97#endif
98
deps/SoftFloat-3e/source/f128M_to_ui32_r_minMag.c deleted-102
...@@ -1,102 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *aPtr, bool exact )
47{
48
49 return f128_to_ui32_r_minMag( *aPtr, exact );
50
51}
52
53#else
54
55uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *aPtr, bool exact )
56{
57 const uint32_t *aWPtr;
58 uint32_t uiA96;
59 int32_t exp;
60 uint64_t sig64;
61 int32_t shiftDist;
62 bool sign;
63 uint32_t z;
64
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 aWPtr = (const uint32_t *) aPtr;
68 uiA96 = aWPtr[indexWordHi( 4 )];
69 exp = expF128UI96( uiA96 );
70 sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )];
71 if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) sig64 |= 1;
72 /*------------------------------------------------------------------------
73 *------------------------------------------------------------------------*/
74 shiftDist = 0x402F - exp;
75 if ( 49 <= shiftDist ) {
76 if ( exact && (exp | sig64) ) {
77 softfloat_exceptionFlags |= softfloat_flag_inexact;
78 }
79 return 0;
80 }
81 /*------------------------------------------------------------------------
82 *------------------------------------------------------------------------*/
83 sign = signF128UI96( uiA96 );
84 if ( sign || (shiftDist < 17) ) {
85 softfloat_raiseFlags( softfloat_flag_invalid );
86 return
87 (exp == 0x7FFF) && sig64 ? ui32_fromNaN
88 : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
89 }
90 /*------------------------------------------------------------------------
91 *------------------------------------------------------------------------*/
92 sig64 |= UINT64_C( 0x0001000000000000 );
93 z = sig64>>shiftDist;
94 if ( exact && ((uint64_t) z<<shiftDist != sig64) ) {
95 softfloat_exceptionFlags |= softfloat_flag_inexact;
96 }
97 return z;
98
99}
100
101#endif
102
deps/SoftFloat-3e/source/f128M_to_ui64.c deleted-102
...@@ -1,102 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46uint_fast64_t
47 f128M_to_ui64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact )
48{
49
50 return f128_to_ui64( *aPtr, roundingMode, exact );
51
52}
53
54#else
55
56uint_fast64_t
57 f128M_to_ui64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact )
58{
59 const uint32_t *aWPtr;
60 uint32_t uiA96;
61 bool sign;
62 int32_t exp;
63 uint32_t sig96;
64 int32_t shiftDist;
65 uint32_t sig[4];
66
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 aWPtr = (const uint32_t *) aPtr;
70 uiA96 = aWPtr[indexWordHi( 4 )];
71 sign = signF128UI96( uiA96 );
72 exp = expF128UI96( uiA96 );
73 sig96 = fracF128UI96( uiA96 );
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 shiftDist = 0x404F - exp;
77 if ( shiftDist < 17 ) {
78 softfloat_raiseFlags( softfloat_flag_invalid );
79 return
80 (exp == 0x7FFF)
81 && (sig96
82 || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
83 | aWPtr[indexWord( 4, 0 )]))
84 ? ui64_fromNaN
85 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
86 }
87 /*------------------------------------------------------------------------
88 *------------------------------------------------------------------------*/
89 if ( exp ) sig96 |= 0x00010000;
90 sig[indexWord( 4, 3 )] = sig96;
91 sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )];
92 sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )];
93 sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )];
94 softfloat_shiftRightJam128M( sig, shiftDist, sig );
95 return
96 softfloat_roundMToUI64(
97 sign, sig + indexMultiwordLo( 4, 3 ), roundingMode, exact );
98
99}
100
101#endif
102
deps/SoftFloat-3e/source/f128M_to_ui64_r_minMag.c deleted-114
...@@ -1,114 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *aPtr, bool exact )
47{
48
49 return f128_to_ui64_r_minMag( *aPtr, exact );
50
51}
52
53#else
54
55uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *aPtr, bool exact )
56{
57 const uint32_t *aWPtr;
58 uint32_t uiA96;
59 bool sign;
60 int32_t exp;
61 uint32_t sig96;
62 int32_t shiftDist;
63 uint32_t sig[4];
64 uint64_t z;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 aWPtr = (const uint32_t *) aPtr;
69 uiA96 = aWPtr[indexWordHi( 4 )];
70 sign = signF128UI96( uiA96 );
71 exp = expF128UI96( uiA96 );
72 sig96 = fracF128UI96( uiA96 );
73 /*------------------------------------------------------------------------
74 *------------------------------------------------------------------------*/
75 shiftDist = 0x403E - exp;
76 if ( shiftDist < 0 ) goto invalid;
77 if ( exact ) {
78 if ( exp ) sig96 |= 0x00010000;
79 sig[indexWord( 4, 3 )] = sig96;
80 sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )];
81 sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )];
82 sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )];
83 softfloat_shiftRightJam128M( sig, shiftDist + 17, sig );
84 z = (uint64_t) sig[indexWord( 4, 2 )]<<32 | sig[indexWord( 4, 1 )];
85 if ( sign && z ) goto invalid;
86 if ( sig[indexWordLo( 4 )] ) {
87 softfloat_exceptionFlags |= softfloat_flag_inexact;
88 }
89 } else {
90 if ( 64 <= shiftDist ) return 0;
91 if ( sign ) goto invalid;
92 z = UINT64_C( 0x8000000000000000 )
93 | (uint64_t) sig96<<47
94 | (uint64_t) aWPtr[indexWord( 4, 2 )]<<15
95 | aWPtr[indexWord( 4, 1 )]>>17;
96 z >>= shiftDist;
97 }
98 return z;
99 /*------------------------------------------------------------------------
100 *------------------------------------------------------------------------*/
101 invalid:
102 softfloat_raiseFlags( softfloat_flag_invalid );
103 return
104 (exp == 0x7FFF)
105 && (sig96
106 || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
107 | aWPtr[indexWord( 4, 0 )]))
108 ? ui64_fromNaN
109 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
110
111}
112
113#endif
114
deps/SoftFloat-3e/source/f128_add.c deleted-78
...@@ -1,78 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float128_t f128_add( float128_t a, float128_t b )
44{
45 union ui128_f128 uA;
46 uint_fast64_t uiA64, uiA0;
47 bool signA;
48 union ui128_f128 uB;
49 uint_fast64_t uiB64, uiB0;
50 bool signB;
51#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
52 float128_t
53 (*magsFuncPtr)(
54 uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
55#endif
56
57 uA.f = a;
58 uiA64 = uA.ui.v64;
59 uiA0 = uA.ui.v0;
60 signA = signF128UI64( uiA64 );
61 uB.f = b;
62 uiB64 = uB.ui.v64;
63 uiB0 = uB.ui.v0;
64 signB = signF128UI64( uiB64 );
65#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
66 if ( signA == signB ) {
67 return softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
68 } else {
69 return softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
70 }
71#else
72 magsFuncPtr =
73 (signA == signB) ? softfloat_addMagsF128 : softfloat_subMagsF128;
74 return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
75#endif
76
77}
78
deps/SoftFloat-3e/source/f128_div.c deleted-199
...@@ -1,199 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float128_t f128_div( float128_t a, float128_t b )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 bool signA;
49 int_fast32_t expA;
50 struct uint128 sigA;
51 union ui128_f128 uB;
52 uint_fast64_t uiB64, uiB0;
53 bool signB;
54 int_fast32_t expB;
55 struct uint128 sigB;
56 bool signZ;
57 struct exp32_sig128 normExpSig;
58 int_fast32_t expZ;
59 struct uint128 rem;
60 uint_fast32_t recip32;
61 int ix;
62 uint_fast64_t q64;
63 uint_fast32_t q;
64 struct uint128 term;
65 uint_fast32_t qs[3];
66 uint_fast64_t sigZExtra;
67 struct uint128 sigZ, uiZ;
68 union ui128_f128 uZ;
69
70 /*------------------------------------------------------------------------
71 *------------------------------------------------------------------------*/
72 uA.f = a;
73 uiA64 = uA.ui.v64;
74 uiA0 = uA.ui.v0;
75 signA = signF128UI64( uiA64 );
76 expA = expF128UI64( uiA64 );
77 sigA.v64 = fracF128UI64( uiA64 );
78 sigA.v0 = uiA0;
79 uB.f = b;
80 uiB64 = uB.ui.v64;
81 uiB0 = uB.ui.v0;
82 signB = signF128UI64( uiB64 );
83 expB = expF128UI64( uiB64 );
84 sigB.v64 = fracF128UI64( uiB64 );
85 sigB.v0 = uiB0;
86 signZ = signA ^ signB;
87 /*------------------------------------------------------------------------
88 *------------------------------------------------------------------------*/
89 if ( expA == 0x7FFF ) {
90 if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
91 if ( expB == 0x7FFF ) {
92 if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
93 goto invalid;
94 }
95 goto infinity;
96 }
97 if ( expB == 0x7FFF ) {
98 if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
99 goto zero;
100 }
101 /*------------------------------------------------------------------------
102 *------------------------------------------------------------------------*/
103 if ( ! expB ) {
104 if ( ! (sigB.v64 | sigB.v0) ) {
105 if ( ! (expA | sigA.v64 | sigA.v0) ) goto invalid;
106 softfloat_raiseFlags( softfloat_flag_infinite );
107 goto infinity;
108 }
109 normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
110 expB = normExpSig.exp;
111 sigB = normExpSig.sig;
112 }
113 if ( ! expA ) {
114 if ( ! (sigA.v64 | sigA.v0) ) goto zero;
115 normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
116 expA = normExpSig.exp;
117 sigA = normExpSig.sig;
118 }
119 /*------------------------------------------------------------------------
120 *------------------------------------------------------------------------*/
121 expZ = expA - expB + 0x3FFE;
122 sigA.v64 |= UINT64_C( 0x0001000000000000 );
123 sigB.v64 |= UINT64_C( 0x0001000000000000 );
124 rem = sigA;
125 if ( softfloat_lt128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ) ) {
126 --expZ;
127 rem = softfloat_add128( sigA.v64, sigA.v0, sigA.v64, sigA.v0 );
128 }
129 recip32 = softfloat_approxRecip32_1( sigB.v64>>17 );
130 ix = 3;
131 for (;;) {
132 q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32;
133 q = (q64 + 0x80000000)>>32;
134 --ix;
135 if ( ix < 0 ) break;
136 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
137 term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
138 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
139 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
140 --q;
141 rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
142 }
143 qs[ix] = q;
144 }
145 /*------------------------------------------------------------------------
146 *------------------------------------------------------------------------*/
147 if ( ((q + 1) & 7) < 2 ) {
148 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
149 term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
150 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
151 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
152 --q;
153 rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
154 } else if ( softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 ) ) {
155 ++q;
156 rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
157 }
158 if ( rem.v64 | rem.v0 ) q |= 1;
159 }
160 /*------------------------------------------------------------------------
161 *------------------------------------------------------------------------*/
162 sigZExtra = (uint64_t) ((uint_fast64_t) q<<60);
163 term = softfloat_shortShiftLeft128( 0, qs[1], 54 );
164 sigZ =
165 softfloat_add128(
166 (uint_fast64_t) qs[2]<<19, ((uint_fast64_t) qs[0]<<25) + (q>>4),
167 term.v64, term.v0
168 );
169 return
170 softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
171 /*------------------------------------------------------------------------
172 *------------------------------------------------------------------------*/
173 propagateNaN:
174 uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
175 goto uiZ;
176 /*------------------------------------------------------------------------
177 *------------------------------------------------------------------------*/
178 invalid:
179 softfloat_raiseFlags( softfloat_flag_invalid );
180 uiZ.v64 = defaultNaNF128UI64;
181 uiZ.v0 = defaultNaNF128UI0;
182 goto uiZ;
183 /*------------------------------------------------------------------------
184 *------------------------------------------------------------------------*/
185 infinity:
186 uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
187 goto uiZ0;
188 /*------------------------------------------------------------------------
189 *------------------------------------------------------------------------*/
190 zero:
191 uiZ.v64 = packToF128UI64( signZ, 0, 0 );
192 uiZ0:
193 uiZ.v0 = 0;
194 uiZ:
195 uZ.ui = uiZ;
196 return uZ.f;
197
198}
199
deps/SoftFloat-3e/source/f128_eq.c deleted-73
...@@ -1,73 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool f128_eq( float128_t a, float128_t b )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 union ui128_f128 uB;
49 uint_fast64_t uiB64, uiB0;
50
51 uA.f = a;
52 uiA64 = uA.ui.v64;
53 uiA0 = uA.ui.v0;
54 uB.f = b;
55 uiB64 = uB.ui.v64;
56 uiB0 = uB.ui.v0;
57 if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
58 if (
59 softfloat_isSigNaNF128UI( uiA64, uiA0 )
60 || softfloat_isSigNaNF128UI( uiB64, uiB0 )
61 ) {
62 softfloat_raiseFlags( softfloat_flag_invalid );
63 }
64 return false;
65 }
66 return
67 (uiA0 == uiB0)
68 && ( (uiA64 == uiB64)
69 || (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
70 );
71
72}
73
deps/SoftFloat-3e/source/f128_eq_signaling.c deleted-67
...@@ -1,67 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43bool f128_eq_signaling( float128_t a, float128_t b )
44{
45 union ui128_f128 uA;
46 uint_fast64_t uiA64, uiA0;
47 union ui128_f128 uB;
48 uint_fast64_t uiB64, uiB0;
49
50 uA.f = a;
51 uiA64 = uA.ui.v64;
52 uiA0 = uA.ui.v0;
53 uB.f = b;
54 uiB64 = uB.ui.v64;
55 uiB0 = uB.ui.v0;
56 if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
57 softfloat_raiseFlags( softfloat_flag_invalid );
58 return false;
59 }
60 return
61 (uiA0 == uiB0)
62 && ( (uiA64 == uiB64)
63 || (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
64 );
65
66}
67
deps/SoftFloat-3e/source/f128_isSignalingNaN.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include "platform.h"
39#include "internals.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43bool f128_isSignalingNaN( float128_t a )
44{
45 union ui128_f128 uA;
46
47 uA.f = a;
48 return softfloat_isSigNaNF128UI( uA.ui.v64, uA.ui.v0 );
49
50}
51
deps/SoftFloat-3e/source/f128_le.c deleted-72
...@@ -1,72 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43bool f128_le( float128_t a, float128_t b )
44{
45 union ui128_f128 uA;
46 uint_fast64_t uiA64, uiA0;
47 union ui128_f128 uB;
48 uint_fast64_t uiB64, uiB0;
49 bool signA, signB;
50
51 uA.f = a;
52 uiA64 = uA.ui.v64;
53 uiA0 = uA.ui.v0;
54 uB.f = b;
55 uiB64 = uB.ui.v64;
56 uiB0 = uB.ui.v0;
57 if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
58 softfloat_raiseFlags( softfloat_flag_invalid );
59 return false;
60 }
61 signA = signF128UI64( uiA64 );
62 signB = signF128UI64( uiB64 );
63 return
64 (signA != signB)
65 ? signA
66 || ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
67 | uiA0 | uiB0)
68 : ((uiA64 == uiB64) && (uiA0 == uiB0))
69 || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
70
71}
72
deps/SoftFloat-3e/source/f128_le_quiet.c deleted-78
...@@ -1,78 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool f128_le_quiet( float128_t a, float128_t b )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 union ui128_f128 uB;
49 uint_fast64_t uiB64, uiB0;
50 bool signA, signB;
51
52 uA.f = a;
53 uiA64 = uA.ui.v64;
54 uiA0 = uA.ui.v0;
55 uB.f = b;
56 uiB64 = uB.ui.v64;
57 uiB0 = uB.ui.v0;
58 if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
59 if (
60 softfloat_isSigNaNF128UI( uiA64, uiA0 )
61 || softfloat_isSigNaNF128UI( uiB64, uiB0 )
62 ) {
63 softfloat_raiseFlags( softfloat_flag_invalid );
64 }
65 return false;
66 }
67 signA = signF128UI64( uiA64 );
68 signB = signF128UI64( uiB64 );
69 return
70 (signA != signB)
71 ? signA
72 || ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
73 | uiA0 | uiB0)
74 : ((uiA64 == uiB64) && (uiA0 == uiB0))
75 || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
76
77}
78
deps/SoftFloat-3e/source/f128_lt.c deleted-72
...@@ -1,72 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43bool f128_lt( float128_t a, float128_t b )
44{
45 union ui128_f128 uA;
46 uint_fast64_t uiA64, uiA0;
47 union ui128_f128 uB;
48 uint_fast64_t uiB64, uiB0;
49 bool signA, signB;
50
51 uA.f = a;
52 uiA64 = uA.ui.v64;
53 uiA0 = uA.ui.v0;
54 uB.f = b;
55 uiB64 = uB.ui.v64;
56 uiB0 = uB.ui.v0;
57 if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
58 softfloat_raiseFlags( softfloat_flag_invalid );
59 return false;
60 }
61 signA = signF128UI64( uiA64 );
62 signB = signF128UI64( uiB64 );
63 return
64 (signA != signB)
65 ? signA
66 && (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
67 | uiA0 | uiB0)
68 : ((uiA64 != uiB64) || (uiA0 != uiB0))
69 && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
70
71}
72
deps/SoftFloat-3e/source/f128_lt_quiet.c deleted-78
...@@ -1,78 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool f128_lt_quiet( float128_t a, float128_t b )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 union ui128_f128 uB;
49 uint_fast64_t uiB64, uiB0;
50 bool signA, signB;
51
52 uA.f = a;
53 uiA64 = uA.ui.v64;
54 uiA0 = uA.ui.v0;
55 uB.f = b;
56 uiB64 = uB.ui.v64;
57 uiB0 = uB.ui.v0;
58 if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
59 if (
60 softfloat_isSigNaNF128UI( uiA64, uiA0 )
61 || softfloat_isSigNaNF128UI( uiB64, uiB0 )
62 ) {
63 softfloat_raiseFlags( softfloat_flag_invalid );
64 }
65 return false;
66 }
67 signA = signF128UI64( uiA64 );
68 signB = signF128UI64( uiB64 );
69 return
70 (signA != signB)
71 ? signA
72 && (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
73 | uiA0 | uiB0)
74 : ((uiA64 != uiB64) || (uiA0 != uiB0))
75 && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
76
77}
78
deps/SoftFloat-3e/source/f128_mul.c deleted-163
...@@ -1,163 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float128_t f128_mul( float128_t a, float128_t b )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 bool signA;
49 int_fast32_t expA;
50 struct uint128 sigA;
51 union ui128_f128 uB;
52 uint_fast64_t uiB64, uiB0;
53 bool signB;
54 int_fast32_t expB;
55 struct uint128 sigB;
56 bool signZ;
57 uint_fast64_t magBits;
58 struct exp32_sig128 normExpSig;
59 int_fast32_t expZ;
60 uint64_t sig256Z[4];
61 uint_fast64_t sigZExtra;
62 struct uint128 sigZ;
63 struct uint128_extra sig128Extra;
64 struct uint128 uiZ;
65 union ui128_f128 uZ;
66
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 uA.f = a;
70 uiA64 = uA.ui.v64;
71 uiA0 = uA.ui.v0;
72 signA = signF128UI64( uiA64 );
73 expA = expF128UI64( uiA64 );
74 sigA.v64 = fracF128UI64( uiA64 );
75 sigA.v0 = uiA0;
76 uB.f = b;
77 uiB64 = uB.ui.v64;
78 uiB0 = uB.ui.v0;
79 signB = signF128UI64( uiB64 );
80 expB = expF128UI64( uiB64 );
81 sigB.v64 = fracF128UI64( uiB64 );
82 sigB.v0 = uiB0;
83 signZ = signA ^ signB;
84 /*------------------------------------------------------------------------
85 *------------------------------------------------------------------------*/
86 if ( expA == 0x7FFF ) {
87 if (
88 (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))
89 ) {
90 goto propagateNaN;
91 }
92 magBits = expB | sigB.v64 | sigB.v0;
93 goto infArg;
94 }
95 if ( expB == 0x7FFF ) {
96 if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
97 magBits = expA | sigA.v64 | sigA.v0;
98 goto infArg;
99 }
100 /*------------------------------------------------------------------------
101 *------------------------------------------------------------------------*/
102 if ( ! expA ) {
103 if ( ! (sigA.v64 | sigA.v0) ) goto zero;
104 normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
105 expA = normExpSig.exp;
106 sigA = normExpSig.sig;
107 }
108 if ( ! expB ) {
109 if ( ! (sigB.v64 | sigB.v0) ) goto zero;
110 normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
111 expB = normExpSig.exp;
112 sigB = normExpSig.sig;
113 }
114 /*------------------------------------------------------------------------
115 *------------------------------------------------------------------------*/
116 expZ = expA + expB - 0x4000;
117 sigA.v64 |= UINT64_C( 0x0001000000000000 );
118 sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 16 );
119 softfloat_mul128To256M( sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z );
120 sigZExtra = sig256Z[indexWord( 4, 1 )] | (sig256Z[indexWord( 4, 0 )] != 0);
121 sigZ =
122 softfloat_add128(
123 sig256Z[indexWord( 4, 3 )], sig256Z[indexWord( 4, 2 )],
124 sigA.v64, sigA.v0
125 );
126 if ( UINT64_C( 0x0002000000000000 ) <= sigZ.v64 ) {
127 ++expZ;
128 sig128Extra =
129 softfloat_shortShiftRightJam128Extra(
130 sigZ.v64, sigZ.v0, sigZExtra, 1 );
131 sigZ = sig128Extra.v;
132 sigZExtra = sig128Extra.extra;
133 }
134 return
135 softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
136 /*------------------------------------------------------------------------
137 *------------------------------------------------------------------------*/
138 propagateNaN:
139 uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
140 goto uiZ;
141 /*------------------------------------------------------------------------
142 *------------------------------------------------------------------------*/
143 infArg:
144 if ( ! magBits ) {
145 softfloat_raiseFlags( softfloat_flag_invalid );
146 uiZ.v64 = defaultNaNF128UI64;
147 uiZ.v0 = defaultNaNF128UI0;
148 goto uiZ;
149 }
150 uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
151 goto uiZ0;
152 /*------------------------------------------------------------------------
153 *------------------------------------------------------------------------*/
154 zero:
155 uiZ.v64 = packToF128UI64( signZ, 0, 0 );
156 uiZ0:
157 uiZ.v0 = 0;
158 uiZ:
159 uZ.ui = uiZ;
160 return uZ.f;
161
162}
163
deps/SoftFloat-3e/source/f128_mulAdd.c deleted-63
...@@ -1,63 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float128_t f128_mulAdd( float128_t a, float128_t b, float128_t c )
43{
44 union ui128_f128 uA;
45 uint_fast64_t uiA64, uiA0;
46 union ui128_f128 uB;
47 uint_fast64_t uiB64, uiB0;
48 union ui128_f128 uC;
49 uint_fast64_t uiC64, uiC0;
50
51 uA.f = a;
52 uiA64 = uA.ui.v64;
53 uiA0 = uA.ui.v0;
54 uB.f = b;
55 uiB64 = uB.ui.v64;
56 uiB0 = uB.ui.v0;
57 uC.f = c;
58 uiC64 = uC.ui.v64;
59 uiC0 = uC.ui.v0;
60 return softfloat_mulAddF128( uiA64, uiA0, uiB64, uiB0, uiC64, uiC0, 0 );
61
62}
63
deps/SoftFloat-3e/source/f128_rem.c deleted-190
...@@ -1,190 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float128_t f128_rem( float128_t a, float128_t b )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 bool signA;
49 int_fast32_t expA;
50 struct uint128 sigA;
51 union ui128_f128 uB;
52 uint_fast64_t uiB64, uiB0;
53 int_fast32_t expB;
54 struct uint128 sigB;
55 struct exp32_sig128 normExpSig;
56 struct uint128 rem;
57 int_fast32_t expDiff;
58 uint_fast32_t q, recip32;
59 uint_fast64_t q64;
60 struct uint128 term, altRem, meanRem;
61 bool signRem;
62 struct uint128 uiZ;
63 union ui128_f128 uZ;
64
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 uA.f = a;
68 uiA64 = uA.ui.v64;
69 uiA0 = uA.ui.v0;
70 signA = signF128UI64( uiA64 );
71 expA = expF128UI64( uiA64 );
72 sigA.v64 = fracF128UI64( uiA64 );
73 sigA.v0 = uiA0;
74 uB.f = b;
75 uiB64 = uB.ui.v64;
76 uiB0 = uB.ui.v0;
77 expB = expF128UI64( uiB64 );
78 sigB.v64 = fracF128UI64( uiB64 );
79 sigB.v0 = uiB0;
80 /*------------------------------------------------------------------------
81 *------------------------------------------------------------------------*/
82 if ( expA == 0x7FFF ) {
83 if (
84 (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))
85 ) {
86 goto propagateNaN;
87 }
88 goto invalid;
89 }
90 if ( expB == 0x7FFF ) {
91 if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
92 return a;
93 }
94 /*------------------------------------------------------------------------
95 *------------------------------------------------------------------------*/
96 if ( ! expB ) {
97 if ( ! (sigB.v64 | sigB.v0) ) goto invalid;
98 normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
99 expB = normExpSig.exp;
100 sigB = normExpSig.sig;
101 }
102 if ( ! expA ) {
103 if ( ! (sigA.v64 | sigA.v0) ) return a;
104 normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
105 expA = normExpSig.exp;
106 sigA = normExpSig.sig;
107 }
108 /*------------------------------------------------------------------------
109 *------------------------------------------------------------------------*/
110 sigA.v64 |= UINT64_C( 0x0001000000000000 );
111 sigB.v64 |= UINT64_C( 0x0001000000000000 );
112 rem = sigA;
113 expDiff = expA - expB;
114 if ( expDiff < 1 ) {
115 if ( expDiff < -1 ) return a;
116 if ( expDiff ) {
117 --expB;
118 sigB = softfloat_add128( sigB.v64, sigB.v0, sigB.v64, sigB.v0 );
119 q = 0;
120 } else {
121 q = softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 );
122 if ( q ) {
123 rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
124 }
125 }
126 } else {
127 recip32 = softfloat_approxRecip32_1( sigB.v64>>17 );
128 expDiff -= 30;
129 for (;;) {
130 q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32;
131 if ( expDiff < 0 ) break;
132 q = (q64 + 0x80000000)>>32;
133 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
134 term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
135 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
136 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
137 rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
138 }
139 expDiff -= 29;
140 }
141 /*--------------------------------------------------------------------
142 | (`expDiff' cannot be less than -29 here.)
143 *--------------------------------------------------------------------*/
144 q = (uint32_t) (q64>>32)>>(~expDiff & 31);
145 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, expDiff + 30 );
146 term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
147 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
148 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
149 altRem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
150 goto selectRem;
151 }
152 }
153 /*------------------------------------------------------------------------
154 *------------------------------------------------------------------------*/
155 do {
156 altRem = rem;
157 ++q;
158 rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
159 } while ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) );
160 selectRem:
161 meanRem = softfloat_add128( rem.v64, rem.v0, altRem.v64, altRem.v0 );
162 if (
163 (meanRem.v64 & UINT64_C( 0x8000000000000000 ))
164 || (! (meanRem.v64 | meanRem.v0) && (q & 1))
165 ) {
166 rem = altRem;
167 }
168 signRem = signA;
169 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
170 signRem = ! signRem;
171 rem = softfloat_sub128( 0, 0, rem.v64, rem.v0 );
172 }
173 return softfloat_normRoundPackToF128( signRem, expB - 1, rem.v64, rem.v0 );
174 /*------------------------------------------------------------------------
175 *------------------------------------------------------------------------*/
176 propagateNaN:
177 uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
178 goto uiZ;
179 /*------------------------------------------------------------------------
180 *------------------------------------------------------------------------*/
181 invalid:
182 softfloat_raiseFlags( softfloat_flag_invalid );
183 uiZ.v64 = defaultNaNF128UI64;
184 uiZ.v0 = defaultNaNF128UI0;
185 uiZ:
186 uZ.ui = uiZ;
187 return uZ.f;
188
189}
190
deps/SoftFloat-3e/source/f128_roundToInt.c deleted-172
...@@ -1,172 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float128_t
45 f128_roundToInt( float128_t a, uint_fast8_t roundingMode, bool exact )
46{
47 union ui128_f128 uA;
48 uint_fast64_t uiA64, uiA0;
49 int_fast32_t exp;
50 struct uint128 uiZ;
51 uint_fast64_t lastBitMask0, roundBitsMask;
52 bool roundNearEven;
53 uint_fast64_t lastBitMask64;
54 union ui128_f128 uZ;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 uA.f = a;
59 uiA64 = uA.ui.v64;
60 uiA0 = uA.ui.v0;
61 exp = expF128UI64( uiA64 );
62 /*------------------------------------------------------------------------
63 *------------------------------------------------------------------------*/
64 if ( 0x402F <= exp ) {
65 /*--------------------------------------------------------------------
66 *--------------------------------------------------------------------*/
67 if ( 0x406F <= exp ) {
68 if ( (exp == 0x7FFF) && (fracF128UI64( uiA64 ) | uiA0) ) {
69 uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, 0, 0 );
70 goto uiZ;
71 }
72 return a;
73 }
74 /*--------------------------------------------------------------------
75 *--------------------------------------------------------------------*/
76 lastBitMask0 = (uint_fast64_t) 2<<(0x406E - exp);
77 roundBitsMask = lastBitMask0 - 1;
78 uiZ.v64 = uiA64;
79 uiZ.v0 = uiA0;
80 roundNearEven = (roundingMode == softfloat_round_near_even);
81 if ( roundNearEven || (roundingMode == softfloat_round_near_maxMag) ) {
82 if ( exp == 0x402F ) {
83 if ( UINT64_C( 0x8000000000000000 ) <= uiZ.v0 ) {
84 ++uiZ.v64;
85 if (
86 roundNearEven
87 && (uiZ.v0 == UINT64_C( 0x8000000000000000 ))
88 ) {
89 uiZ.v64 &= ~1;
90 }
91 }
92 } else {
93 uiZ = softfloat_add128( uiZ.v64, uiZ.v0, 0, lastBitMask0>>1 );
94 if ( roundNearEven && !(uiZ.v0 & roundBitsMask) ) {
95 uiZ.v0 &= ~lastBitMask0;
96 }
97 }
98 } else if (
99 roundingMode
100 == (signF128UI64( uiZ.v64 ) ? softfloat_round_min
101 : softfloat_round_max)
102 ) {
103 uiZ = softfloat_add128( uiZ.v64, uiZ.v0, 0, roundBitsMask );
104 }
105 uiZ.v0 &= ~roundBitsMask;
106 lastBitMask64 = !lastBitMask0;
107 } else {
108 /*--------------------------------------------------------------------
109 *--------------------------------------------------------------------*/
110 if ( exp < 0x3FFF ) {
111 if ( !((uiA64 & UINT64_C( 0x7FFFFFFFFFFFFFFF )) | uiA0) ) return a;
112 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
113 uiZ.v64 = uiA64 & packToF128UI64( 1, 0, 0 );
114 uiZ.v0 = 0;
115 switch ( roundingMode ) {
116 case softfloat_round_near_even:
117 if ( !(fracF128UI64( uiA64 ) | uiA0) ) break;
118 case softfloat_round_near_maxMag:
119 if ( exp == 0x3FFE ) uiZ.v64 |= packToF128UI64( 0, 0x3FFF, 0 );
120 break;
121 case softfloat_round_min:
122 if ( uiZ.v64 ) uiZ.v64 = packToF128UI64( 1, 0x3FFF, 0 );
123 break;
124 case softfloat_round_max:
125 if ( !uiZ.v64 ) uiZ.v64 = packToF128UI64( 0, 0x3FFF, 0 );
126 break;
127#ifdef SOFTFLOAT_ROUND_ODD
128 case softfloat_round_odd:
129 uiZ.v64 |= packToF128UI64( 0, 0x3FFF, 0 );
130 break;
131#endif
132 }
133 goto uiZ;
134 }
135 /*--------------------------------------------------------------------
136 *--------------------------------------------------------------------*/
137 uiZ.v64 = uiA64;
138 uiZ.v0 = 0;
139 lastBitMask64 = (uint_fast64_t) 1<<(0x402F - exp);
140 roundBitsMask = lastBitMask64 - 1;
141 if ( roundingMode == softfloat_round_near_maxMag ) {
142 uiZ.v64 += lastBitMask64>>1;
143 } else if ( roundingMode == softfloat_round_near_even ) {
144 uiZ.v64 += lastBitMask64>>1;
145 if ( !((uiZ.v64 & roundBitsMask) | uiA0) ) {
146 uiZ.v64 &= ~lastBitMask64;
147 }
148 } else if (
149 roundingMode
150 == (signF128UI64( uiZ.v64 ) ? softfloat_round_min
151 : softfloat_round_max)
152 ) {
153 uiZ.v64 = (uiZ.v64 | (uiA0 != 0)) + roundBitsMask;
154 }
155 uiZ.v64 &= ~roundBitsMask;
156 lastBitMask0 = 0;
157 }
158 if ( (uiZ.v64 != uiA64) || (uiZ.v0 != uiA0) ) {
159#ifdef SOFTFLOAT_ROUND_ODD
160 if ( roundingMode == softfloat_round_odd ) {
161 uiZ.v64 |= lastBitMask64;
162 uiZ.v0 |= lastBitMask0;
163 }
164#endif
165 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
166 }
167 uiZ:
168 uZ.ui = uiZ;
169 return uZ.f;
170
171}
172
deps/SoftFloat-3e/source/f128_sqrt.c deleted-201
...@@ -1,201 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float128_t f128_sqrt( float128_t a )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 bool signA;
49 int_fast32_t expA;
50 struct uint128 sigA, uiZ;
51 struct exp32_sig128 normExpSig;
52 int_fast32_t expZ;
53 uint_fast32_t sig32A, recipSqrt32, sig32Z;
54 struct uint128 rem;
55 uint32_t qs[3];
56 uint_fast32_t q;
57 uint_fast64_t x64, sig64Z;
58 struct uint128 y, term;
59 uint_fast64_t sigZExtra;
60 struct uint128 sigZ;
61 union ui128_f128 uZ;
62
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 uA.f = a;
66 uiA64 = uA.ui.v64;
67 uiA0 = uA.ui.v0;
68 signA = signF128UI64( uiA64 );
69 expA = expF128UI64( uiA64 );
70 sigA.v64 = fracF128UI64( uiA64 );
71 sigA.v0 = uiA0;
72 /*------------------------------------------------------------------------
73 *------------------------------------------------------------------------*/
74 if ( expA == 0x7FFF ) {
75 if ( sigA.v64 | sigA.v0 ) {
76 uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, 0, 0 );
77 goto uiZ;
78 }
79 if ( ! signA ) return a;
80 goto invalid;
81 }
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( signA ) {
85 if ( ! (expA | sigA.v64 | sigA.v0) ) return a;
86 goto invalid;
87 }
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 if ( ! expA ) {
91 if ( ! (sigA.v64 | sigA.v0) ) return a;
92 normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
93 expA = normExpSig.exp;
94 sigA = normExpSig.sig;
95 }
96 /*------------------------------------------------------------------------
97 | (`sig32Z' is guaranteed to be a lower bound on the square root of
98 | `sig32A', which makes `sig32Z' also a lower bound on the square root of
99 | `sigA'.)
100 *------------------------------------------------------------------------*/
101 expZ = ((expA - 0x3FFF)>>1) + 0x3FFE;
102 expA &= 1;
103 sigA.v64 |= UINT64_C( 0x0001000000000000 );
104 sig32A = sigA.v64>>17;
105 recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A );
106 sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32;
107 if ( expA ) {
108 sig32Z >>= 1;
109 rem = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 12 );
110 } else {
111 rem = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 13 );
112 }
113 qs[2] = sig32Z;
114 rem.v64 -= (uint_fast64_t) sig32Z * sig32Z;
115 /*------------------------------------------------------------------------
116 *------------------------------------------------------------------------*/
117 q = ((uint32_t) (rem.v64>>2) * (uint_fast64_t) recipSqrt32)>>32;
118 x64 = (uint_fast64_t) sig32Z<<32;
119 sig64Z = x64 + ((uint_fast64_t) q<<3);
120 y = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
121 /*------------------------------------------------------------------------
122 | (Repeating this loop is a rare occurrence.)
123 *------------------------------------------------------------------------*/
124 for (;;) {
125 term = softfloat_mul64ByShifted32To128( x64 + sig64Z, q );
126 rem = softfloat_sub128( y.v64, y.v0, term.v64, term.v0 );
127 if ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ) break;
128 --q;
129 sig64Z -= 1<<3;
130 }
131 qs[1] = q;
132 /*------------------------------------------------------------------------
133 *------------------------------------------------------------------------*/
134 q = ((rem.v64>>2) * recipSqrt32)>>32;
135 y = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
136 sig64Z <<= 1;
137 /*------------------------------------------------------------------------
138 | (Repeating this loop is a rare occurrence.)
139 *------------------------------------------------------------------------*/
140 for (;;) {
141 term = softfloat_shortShiftLeft128( 0, sig64Z, 32 );
142 term = softfloat_add128( term.v64, term.v0, 0, (uint_fast64_t) q<<6 );
143 term = softfloat_mul128By32( term.v64, term.v0, q );
144 rem = softfloat_sub128( y.v64, y.v0, term.v64, term.v0 );
145 if ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ) break;
146 --q;
147 }
148 qs[0] = q;
149 /*------------------------------------------------------------------------
150 *------------------------------------------------------------------------*/
151 q = (((rem.v64>>2) * recipSqrt32)>>32) + 2;
152 sigZExtra = (uint64_t) ((uint_fast64_t) q<<59);
153 term = softfloat_shortShiftLeft128( 0, qs[1], 53 );
154 sigZ =
155 softfloat_add128(
156 (uint_fast64_t) qs[2]<<18, ((uint_fast64_t) qs[0]<<24) + (q>>5),
157 term.v64, term.v0
158 );
159 /*------------------------------------------------------------------------
160 *------------------------------------------------------------------------*/
161 if ( (q & 0xF) <= 2 ) {
162 q &= ~3;
163 sigZExtra = (uint64_t) ((uint_fast64_t) q<<59);
164 y = softfloat_shortShiftLeft128( sigZ.v64, sigZ.v0, 6 );
165 y.v0 |= sigZExtra>>58;
166 term = softfloat_sub128( y.v64, y.v0, 0, q );
167 y = softfloat_mul64ByShifted32To128( term.v0, q );
168 term = softfloat_mul64ByShifted32To128( term.v64, q );
169 term = softfloat_add128( term.v64, term.v0, 0, y.v64 );
170 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 20 );
171 term = softfloat_sub128( term.v64, term.v0, rem.v64, rem.v0 );
172 /*--------------------------------------------------------------------
173 | The concatenation of `term' and `y.v0' is now the negative remainder
174 | (3 words altogether).
175 *--------------------------------------------------------------------*/
176 if ( term.v64 & UINT64_C( 0x8000000000000000 ) ) {
177 sigZExtra |= 1;
178 } else {
179 if ( term.v64 | term.v0 | y.v0 ) {
180 if ( sigZExtra ) {
181 --sigZExtra;
182 } else {
183 sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, 0, 1 );
184 sigZExtra = ~0;
185 }
186 }
187 }
188 }
189 return softfloat_roundPackToF128( 0, expZ, sigZ.v64, sigZ.v0, sigZExtra );
190 /*------------------------------------------------------------------------
191 *------------------------------------------------------------------------*/
192 invalid:
193 softfloat_raiseFlags( softfloat_flag_invalid );
194 uiZ.v64 = defaultNaNF128UI64;
195 uiZ.v0 = defaultNaNF128UI0;
196 uiZ:
197 uZ.ui = uiZ;
198 return uZ.f;
199
200}
201
deps/SoftFloat-3e/source/f128_sub.c deleted-78
...@@ -1,78 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float128_t f128_sub( float128_t a, float128_t b )
44{
45 union ui128_f128 uA;
46 uint_fast64_t uiA64, uiA0;
47 bool signA;
48 union ui128_f128 uB;
49 uint_fast64_t uiB64, uiB0;
50 bool signB;
51#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
52 float128_t
53 (*magsFuncPtr)(
54 uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
55#endif
56
57 uA.f = a;
58 uiA64 = uA.ui.v64;
59 uiA0 = uA.ui.v0;
60 signA = signF128UI64( uiA64 );
61 uB.f = b;
62 uiB64 = uB.ui.v64;
63 uiB0 = uB.ui.v0;
64 signB = signF128UI64( uiB64 );
65#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
66 if ( signA == signB ) {
67 return softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
68 } else {
69 return softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
70 }
71#else
72 magsFuncPtr =
73 (signA == signB) ? softfloat_subMagsF128 : softfloat_addMagsF128;
74 return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
75#endif
76
77}
78
deps/SoftFloat-3e/source/f128_to_extF80.c deleted-109
...@@ -1,109 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44extFloat80_t f128_to_extF80( float128_t a )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 bool sign;
49 int_fast32_t exp;
50 uint_fast64_t frac64, frac0;
51 struct commonNaN commonNaN;
52 struct uint128 uiZ;
53 uint_fast16_t uiZ64;
54 uint_fast64_t uiZ0;
55 struct exp32_sig128 normExpSig;
56 struct uint128 sig128;
57 union { struct extFloat80M s; extFloat80_t f; } uZ;
58
59 /*------------------------------------------------------------------------
60 *------------------------------------------------------------------------*/
61 uA.f = a;
62 uiA64 = uA.ui.v64;
63 uiA0 = uA.ui.v0;
64 sign = signF128UI64( uiA64 );
65 exp = expF128UI64( uiA64 );
66 frac64 = fracF128UI64( uiA64 );
67 frac0 = uiA0;
68 /*------------------------------------------------------------------------
69 *------------------------------------------------------------------------*/
70 if ( exp == 0x7FFF ) {
71 if ( frac64 | frac0 ) {
72 softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN );
73 uiZ = softfloat_commonNaNToExtF80UI( &commonNaN );
74 uiZ64 = uiZ.v64;
75 uiZ0 = uiZ.v0;
76 } else {
77 uiZ64 = packToExtF80UI64( sign, 0x7FFF );
78 uiZ0 = UINT64_C( 0x8000000000000000 );
79 }
80 goto uiZ;
81 }
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( ! exp ) {
85 if ( ! (frac64 | frac0) ) {
86 uiZ64 = packToExtF80UI64( sign, 0 );
87 uiZ0 = 0;
88 goto uiZ;
89 }
90 normExpSig = softfloat_normSubnormalF128Sig( frac64, frac0 );
91 exp = normExpSig.exp;
92 frac64 = normExpSig.sig.v64;
93 frac0 = normExpSig.sig.v0;
94 }
95 /*------------------------------------------------------------------------
96 *------------------------------------------------------------------------*/
97 sig128 =
98 softfloat_shortShiftLeft128(
99 frac64 | UINT64_C( 0x0001000000000000 ), frac0, 15 );
100 return softfloat_roundPackToExtF80( sign, exp, sig128.v64, sig128.v0, 80 );
101 /*------------------------------------------------------------------------
102 *------------------------------------------------------------------------*/
103 uiZ:
104 uZ.s.signExp = uiZ64;
105 uZ.s.signif = uiZ0;
106 return uZ.f;
107
108}
109
deps/SoftFloat-3e/source/f128_to_f16.c deleted-95
...@@ -1,95 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float16_t f128_to_f16( float128_t a )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 bool sign;
49 int_fast32_t exp;
50 uint_fast64_t frac64;
51 struct commonNaN commonNaN;
52 uint_fast16_t uiZ, frac16;
53 union ui16_f16 uZ;
54
55 /*------------------------------------------------------------------------
56 *------------------------------------------------------------------------*/
57 uA.f = a;
58 uiA64 = uA.ui.v64;
59 uiA0 = uA.ui.v0;
60 sign = signF128UI64( uiA64 );
61 exp = expF128UI64( uiA64 );
62 frac64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 if ( exp == 0x7FFF ) {
66 if ( frac64 ) {
67 softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN );
68 uiZ = softfloat_commonNaNToF16UI( &commonNaN );
69 } else {
70 uiZ = packToF16UI( sign, 0x1F, 0 );
71 }
72 goto uiZ;
73 }
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 frac16 = softfloat_shortShiftRightJam64( frac64, 34 );
77 if ( ! (exp | frac16) ) {
78 uiZ = packToF16UI( sign, 0, 0 );
79 goto uiZ;
80 }
81 /*------------------------------------------------------------------------
82 *------------------------------------------------------------------------*/
83 exp -= 0x3FF1;
84 if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
85 if ( exp < -0x40 ) exp = -0x40;
86 }
87 return softfloat_roundPackToF16( sign, exp, frac16 | 0x4000 );
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 uiZ:
91 uZ.ui = uiZ;
92 return uZ.f;
93
94}
95
deps/SoftFloat-3e/source/f128_to_f32.c deleted-95
...@@ -1,95 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float32_t f128_to_f32( float128_t a )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 bool sign;
49 int_fast32_t exp;
50 uint_fast64_t frac64;
51 struct commonNaN commonNaN;
52 uint_fast32_t uiZ, frac32;
53 union ui32_f32 uZ;
54
55 /*------------------------------------------------------------------------
56 *------------------------------------------------------------------------*/
57 uA.f = a;
58 uiA64 = uA.ui.v64;
59 uiA0 = uA.ui.v0;
60 sign = signF128UI64( uiA64 );
61 exp = expF128UI64( uiA64 );
62 frac64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 if ( exp == 0x7FFF ) {
66 if ( frac64 ) {
67 softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN );
68 uiZ = softfloat_commonNaNToF32UI( &commonNaN );
69 } else {
70 uiZ = packToF32UI( sign, 0xFF, 0 );
71 }
72 goto uiZ;
73 }
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 frac32 = softfloat_shortShiftRightJam64( frac64, 18 );
77 if ( ! (exp | frac32) ) {
78 uiZ = packToF32UI( sign, 0, 0 );
79 goto uiZ;
80 }
81 /*------------------------------------------------------------------------
82 *------------------------------------------------------------------------*/
83 exp -= 0x3F81;
84 if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
85 if ( exp < -0x1000 ) exp = -0x1000;
86 }
87 return softfloat_roundPackToF32( sign, exp, frac32 | 0x40000000 );
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 uiZ:
91 uZ.ui = uiZ;
92 return uZ.f;
93
94}
95
deps/SoftFloat-3e/source/f128_to_f64.c deleted-100
...@@ -1,100 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float64_t f128_to_f64( float128_t a )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 bool sign;
49 int_fast32_t exp;
50 uint_fast64_t frac64, frac0;
51 struct commonNaN commonNaN;
52 uint_fast64_t uiZ;
53 struct uint128 frac128;
54 union ui64_f64 uZ;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 uA.f = a;
59 uiA64 = uA.ui.v64;
60 uiA0 = uA.ui.v0;
61 sign = signF128UI64( uiA64 );
62 exp = expF128UI64( uiA64 );
63 frac64 = fracF128UI64( uiA64 );
64 frac0 = uiA0;
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 if ( exp == 0x7FFF ) {
68 if ( frac64 | frac0 ) {
69 softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN );
70 uiZ = softfloat_commonNaNToF64UI( &commonNaN );
71 } else {
72 uiZ = packToF64UI( sign, 0x7FF, 0 );
73 }
74 goto uiZ;
75 }
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 frac128 = softfloat_shortShiftLeft128( frac64, frac0, 14 );
79 frac64 = frac128.v64 | (frac128.v0 != 0);
80 if ( ! (exp | frac64) ) {
81 uiZ = packToF64UI( sign, 0, 0 );
82 goto uiZ;
83 }
84 /*------------------------------------------------------------------------
85 *------------------------------------------------------------------------*/
86 exp -= 0x3C01;
87 if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
88 if ( exp < -0x1000 ) exp = -0x1000;
89 }
90 return
91 softfloat_roundPackToF64(
92 sign, exp, frac64 | UINT64_C( 0x4000000000000000 ) );
93 /*------------------------------------------------------------------------
94 *------------------------------------------------------------------------*/
95 uiZ:
96 uZ.ui = uiZ;
97 return uZ.f;
98
99}
100
deps/SoftFloat-3e/source/f128_to_i32.c deleted-85
...@@ -1,85 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast32_t f128_to_i32( float128_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 bool sign;
49 int_fast32_t exp;
50 uint_fast64_t sig64, sig0;
51 int_fast32_t shiftDist;
52
53 /*------------------------------------------------------------------------
54 *------------------------------------------------------------------------*/
55 uA.f = a;
56 uiA64 = uA.ui.v64;
57 uiA0 = uA.ui.v0;
58 sign = signF128UI64( uiA64 );
59 exp = expF128UI64( uiA64 );
60 sig64 = fracF128UI64( uiA64 );
61 sig0 = uiA0;
62 /*------------------------------------------------------------------------
63 *------------------------------------------------------------------------*/
64#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
65 if ( (exp == 0x7FFF) && (sig64 | sig0) ) {
66#if (i32_fromNaN == i32_fromPosOverflow)
67 sign = 0;
68#elif (i32_fromNaN == i32_fromNegOverflow)
69 sign = 1;
70#else
71 softfloat_raiseFlags( softfloat_flag_invalid );
72 return i32_fromNaN;
73#endif
74 }
75#endif
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
79 sig64 |= (sig0 != 0);
80 shiftDist = 0x4023 - exp;
81 if ( 0 < shiftDist ) sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
82 return softfloat_roundToI32( sign, sig64, roundingMode, exact );
83
84}
85
deps/SoftFloat-3e/source/f128_to_i32_r_minMag.c deleted-100
...@@ -1,100 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast32_t f128_to_i32_r_minMag( float128_t a, bool exact )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 int_fast32_t exp;
49 uint_fast64_t sig64;
50 int_fast32_t shiftDist;
51 bool sign;
52 int_fast32_t absZ;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA64 = uA.ui.v64;
58 uiA0 = uA.ui.v0;
59 exp = expF128UI64( uiA64 );
60 sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
61 /*------------------------------------------------------------------------
62 *------------------------------------------------------------------------*/
63 shiftDist = 0x402F - exp;
64 if ( 49 <= shiftDist ) {
65 if ( exact && (exp | sig64) ) {
66 softfloat_exceptionFlags |= softfloat_flag_inexact;
67 }
68 return 0;
69 }
70 /*------------------------------------------------------------------------
71 *------------------------------------------------------------------------*/
72 sign = signF128UI64( uiA64 );
73 if ( shiftDist < 18 ) {
74 if (
75 sign && (shiftDist == 17)
76 && (sig64 < UINT64_C( 0x0000000000020000 ))
77 ) {
78 if ( exact && sig64 ) {
79 softfloat_exceptionFlags |= softfloat_flag_inexact;
80 }
81 return -0x7FFFFFFF - 1;
82 }
83 softfloat_raiseFlags( softfloat_flag_invalid );
84 return
85 (exp == 0x7FFF) && sig64 ? i32_fromNaN
86 : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
87 }
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 sig64 |= UINT64_C( 0x0001000000000000 );
91 absZ = sig64>>shiftDist;
92 if (
93 exact && ((uint_fast64_t) (uint_fast32_t) absZ<<shiftDist != sig64)
94 ) {
95 softfloat_exceptionFlags |= softfloat_flag_inexact;
96 }
97 return sign ? -absZ : absZ;
98
99}
100
deps/SoftFloat-3e/source/f128_to_i64.c deleted-95
...@@ -1,95 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast64_t f128_to_i64( float128_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 bool sign;
49 int_fast32_t exp;
50 uint_fast64_t sig64, sig0;
51 int_fast32_t shiftDist;
52 struct uint128 sig128;
53 struct uint64_extra sigExtra;
54
55 /*------------------------------------------------------------------------
56 *------------------------------------------------------------------------*/
57 uA.f = a;
58 uiA64 = uA.ui.v64;
59 uiA0 = uA.ui.v0;
60 sign = signF128UI64( uiA64 );
61 exp = expF128UI64( uiA64 );
62 sig64 = fracF128UI64( uiA64 );
63 sig0 = uiA0;
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 shiftDist = 0x402F - exp;
67 if ( shiftDist <= 0 ) {
68 /*--------------------------------------------------------------------
69 *--------------------------------------------------------------------*/
70 if ( shiftDist < -15 ) {
71 softfloat_raiseFlags( softfloat_flag_invalid );
72 return
73 (exp == 0x7FFF) && (sig64 | sig0) ? i64_fromNaN
74 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
75 }
76 /*--------------------------------------------------------------------
77 *--------------------------------------------------------------------*/
78 sig64 |= UINT64_C( 0x0001000000000000 );
79 if ( shiftDist ) {
80 sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftDist );
81 sig64 = sig128.v64;
82 sig0 = sig128.v0;
83 }
84 } else {
85 /*--------------------------------------------------------------------
86 *--------------------------------------------------------------------*/
87 if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
88 sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftDist );
89 sig64 = sigExtra.v;
90 sig0 = sigExtra.extra;
91 }
92 return softfloat_roundToI64( sign, sig64, sig0, roundingMode, exact );
93
94}
95
deps/SoftFloat-3e/source/f128_to_i64_r_minMag.c deleted-113
...@@ -1,113 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast64_t f128_to_i64_r_minMag( float128_t a, bool exact )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 bool sign;
49 int_fast32_t exp;
50 uint_fast64_t sig64, sig0;
51 int_fast32_t shiftDist;
52 int_fast8_t negShiftDist;
53 int_fast64_t absZ;
54
55 /*------------------------------------------------------------------------
56 *------------------------------------------------------------------------*/
57 uA.f = a;
58 uiA64 = uA.ui.v64;
59 uiA0 = uA.ui.v0;
60 sign = signF128UI64( uiA64 );
61 exp = expF128UI64( uiA64 );
62 sig64 = fracF128UI64( uiA64 );
63 sig0 = uiA0;
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 shiftDist = 0x402F - exp;
67 if ( shiftDist < 0 ) {
68 /*--------------------------------------------------------------------
69 *--------------------------------------------------------------------*/
70 if ( shiftDist < -14 ) {
71 if (
72 (uiA64 == UINT64_C( 0xC03E000000000000 ))
73 && (sig0 < UINT64_C( 0x0002000000000000 ))
74 ) {
75 if ( exact && sig0 ) {
76 softfloat_exceptionFlags |= softfloat_flag_inexact;
77 }
78 return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1;
79 }
80 softfloat_raiseFlags( softfloat_flag_invalid );
81 return
82 (exp == 0x7FFF) && (sig64 | sig0) ? i64_fromNaN
83 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
84 }
85 /*--------------------------------------------------------------------
86 *--------------------------------------------------------------------*/
87 sig64 |= UINT64_C( 0x0001000000000000 );
88 negShiftDist = -shiftDist;
89 absZ = sig64<<negShiftDist | sig0>>(shiftDist & 63);
90 if ( exact && (uint64_t) (sig0<<negShiftDist) ) {
91 softfloat_exceptionFlags |= softfloat_flag_inexact;
92 }
93 } else {
94 /*--------------------------------------------------------------------
95 *--------------------------------------------------------------------*/
96 if ( 49 <= shiftDist ) {
97 if ( exact && (exp | sig64 | sig0) ) {
98 softfloat_exceptionFlags |= softfloat_flag_inexact;
99 }
100 return 0;
101 }
102 /*--------------------------------------------------------------------
103 *--------------------------------------------------------------------*/
104 sig64 |= UINT64_C( 0x0001000000000000 );
105 absZ = sig64>>shiftDist;
106 if ( exact && (sig0 || (absZ<<shiftDist != sig64)) ) {
107 softfloat_exceptionFlags |= softfloat_flag_inexact;
108 }
109 }
110 return sign ? -absZ : absZ;
111
112}
113
deps/SoftFloat-3e/source/f128_to_ui32.c deleted-86
...@@ -1,86 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast32_t
45 f128_to_ui32( float128_t a, uint_fast8_t roundingMode, bool exact )
46{
47 union ui128_f128 uA;
48 uint_fast64_t uiA64, uiA0;
49 bool sign;
50 int_fast32_t exp;
51 uint_fast64_t sig64;
52 int_fast32_t shiftDist;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA64 = uA.ui.v64;
58 uiA0 = uA.ui.v0;
59 sign = signF128UI64( uiA64 );
60 exp = expF128UI64( uiA64 );
61 sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
62 /*------------------------------------------------------------------------
63 *------------------------------------------------------------------------*/
64#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
65 if ( (exp == 0x7FFF) && sig64 ) {
66#if (ui32_fromNaN == ui32_fromPosOverflow)
67 sign = 0;
68#elif (ui32_fromNaN == ui32_fromNegOverflow)
69 sign = 1;
70#else
71 softfloat_raiseFlags( softfloat_flag_invalid );
72 return ui32_fromNaN;
73#endif
74 }
75#endif
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
79 shiftDist = 0x4023 - exp;
80 if ( 0 < shiftDist ) {
81 sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
82 }
83 return softfloat_roundToUI32( sign, sig64, roundingMode, exact );
84
85}
86
deps/SoftFloat-3e/source/f128_to_ui32_r_minMag.c deleted-89
...@@ -1,89 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast32_t f128_to_ui32_r_minMag( float128_t a, bool exact )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 int_fast32_t exp;
49 uint_fast64_t sig64;
50 int_fast32_t shiftDist;
51 bool sign;
52 uint_fast32_t z;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA64 = uA.ui.v64;
58 uiA0 = uA.ui.v0;
59 exp = expF128UI64( uiA64 );
60 sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
61 /*------------------------------------------------------------------------
62 *------------------------------------------------------------------------*/
63 shiftDist = 0x402F - exp;
64 if ( 49 <= shiftDist ) {
65 if ( exact && (exp | sig64) ) {
66 softfloat_exceptionFlags |= softfloat_flag_inexact;
67 }
68 return 0;
69 }
70 /*------------------------------------------------------------------------
71 *------------------------------------------------------------------------*/
72 sign = signF128UI64( uiA64 );
73 if ( sign || (shiftDist < 17) ) {
74 softfloat_raiseFlags( softfloat_flag_invalid );
75 return
76 (exp == 0x7FFF) && sig64 ? ui32_fromNaN
77 : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
78 }
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 sig64 |= UINT64_C( 0x0001000000000000 );
82 z = sig64>>shiftDist;
83 if ( exact && ((uint_fast64_t) z<<shiftDist != sig64) ) {
84 softfloat_exceptionFlags |= softfloat_flag_inexact;
85 }
86 return z;
87
88}
89
deps/SoftFloat-3e/source/f128_to_ui64.c deleted-96
...@@ -1,96 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast64_t
45 f128_to_ui64( float128_t a, uint_fast8_t roundingMode, bool exact )
46{
47 union ui128_f128 uA;
48 uint_fast64_t uiA64, uiA0;
49 bool sign;
50 int_fast32_t exp;
51 uint_fast64_t sig64, sig0;
52 int_fast32_t shiftDist;
53 struct uint128 sig128;
54 struct uint64_extra sigExtra;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 uA.f = a;
59 uiA64 = uA.ui.v64;
60 uiA0 = uA.ui.v0;
61 sign = signF128UI64( uiA64 );
62 exp = expF128UI64( uiA64 );
63 sig64 = fracF128UI64( uiA64 );
64 sig0 = uiA0;
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 shiftDist = 0x402F - exp;
68 if ( shiftDist <= 0 ) {
69 /*--------------------------------------------------------------------
70 *--------------------------------------------------------------------*/
71 if ( shiftDist < -15 ) {
72 softfloat_raiseFlags( softfloat_flag_invalid );
73 return
74 (exp == 0x7FFF) && (sig64 | sig0) ? ui64_fromNaN
75 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
76 }
77 /*--------------------------------------------------------------------
78 *--------------------------------------------------------------------*/
79 sig64 |= UINT64_C( 0x0001000000000000 );
80 if ( shiftDist ) {
81 sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftDist );
82 sig64 = sig128.v64;
83 sig0 = sig128.v0;
84 }
85 } else {
86 /*--------------------------------------------------------------------
87 *--------------------------------------------------------------------*/
88 if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
89 sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftDist );
90 sig64 = sigExtra.v;
91 sig0 = sigExtra.extra;
92 }
93 return softfloat_roundToUI64( sign, sig64, sig0, roundingMode, exact );
94
95}
96
deps/SoftFloat-3e/source/f128_to_ui64_r_minMag.c deleted-105
...@@ -1,105 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast64_t f128_to_ui64_r_minMag( float128_t a, bool exact )
45{
46 union ui128_f128 uA;
47 uint_fast64_t uiA64, uiA0;
48 bool sign;
49 int_fast32_t exp;
50 uint_fast64_t sig64, sig0;
51 int_fast32_t shiftDist;
52 int_fast8_t negShiftDist;
53 uint_fast64_t z;
54
55 /*------------------------------------------------------------------------
56 *------------------------------------------------------------------------*/
57 uA.f = a;
58 uiA64 = uA.ui.v64;
59 uiA0 = uA.ui.v0;
60 sign = signF128UI64( uiA64 );
61 exp = expF128UI64( uiA64 );
62 sig64 = fracF128UI64( uiA64 );
63 sig0 = uiA0;
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 shiftDist = 0x402F - exp;
67 if ( shiftDist < 0 ) {
68 /*--------------------------------------------------------------------
69 *--------------------------------------------------------------------*/
70 if ( sign || (shiftDist < -15) ) goto invalid;
71 sig64 |= UINT64_C( 0x0001000000000000 );
72 negShiftDist = -shiftDist;
73 z = sig64<<negShiftDist | sig0>>(shiftDist & 63);
74 if ( exact && (uint64_t) (sig0<<negShiftDist) ) {
75 softfloat_exceptionFlags |= softfloat_flag_inexact;
76 }
77 } else {
78 /*--------------------------------------------------------------------
79 *--------------------------------------------------------------------*/
80 if ( 49 <= shiftDist ) {
81 if ( exact && (exp | sig64 | sig0) ) {
82 softfloat_exceptionFlags |= softfloat_flag_inexact;
83 }
84 return 0;
85 }
86 /*--------------------------------------------------------------------
87 *--------------------------------------------------------------------*/
88 if ( sign ) goto invalid;
89 sig64 |= UINT64_C( 0x0001000000000000 );
90 z = sig64>>shiftDist;
91 if ( exact && (sig0 || (z<<shiftDist != sig64)) ) {
92 softfloat_exceptionFlags |= softfloat_flag_inexact;
93 }
94 }
95 return z;
96 /*------------------------------------------------------------------------
97 *------------------------------------------------------------------------*/
98 invalid:
99 softfloat_raiseFlags( softfloat_flag_invalid );
100 return
101 (exp == 0x7FFF) && (sig64 | sig0) ? ui64_fromNaN
102 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
103
104}
105
deps/SoftFloat-3e/source/f16_add.c deleted-70
...@@ -1,70 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float16_t f16_add( float16_t a, float16_t b )
44{
45 union ui16_f16 uA;
46 uint_fast16_t uiA;
47 union ui16_f16 uB;
48 uint_fast16_t uiB;
49#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1)
50 float16_t (*magsFuncPtr)( uint_fast16_t, uint_fast16_t );
51#endif
52
53 uA.f = a;
54 uiA = uA.ui;
55 uB.f = b;
56 uiB = uB.ui;
57#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
58 if ( signF16UI( uiA ^ uiB ) ) {
59 return softfloat_subMagsF16( uiA, uiB );
60 } else {
61 return softfloat_addMagsF16( uiA, uiB );
62 }
63#else
64 magsFuncPtr =
65 signF16UI( uiA ^ uiB ) ? softfloat_subMagsF16 : softfloat_addMagsF16;
66 return (*magsFuncPtr)( uiA, uiB );
67#endif
68
69}
70
deps/SoftFloat-3e/source/f16_div.c deleted-186
...@@ -1,186 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44extern const uint16_t softfloat_approxRecip_1k0s[];
45extern const uint16_t softfloat_approxRecip_1k1s[];
46
47float16_t f16_div( float16_t a, float16_t b )
48{
49 union ui16_f16 uA;
50 uint_fast16_t uiA;
51 bool signA;
52 int_fast8_t expA;
53 uint_fast16_t sigA;
54 union ui16_f16 uB;
55 uint_fast16_t uiB;
56 bool signB;
57 int_fast8_t expB;
58 uint_fast16_t sigB;
59 bool signZ;
60 struct exp8_sig16 normExpSig;
61 int_fast8_t expZ;
62#ifdef SOFTFLOAT_FAST_DIV32TO16
63 uint_fast32_t sig32A;
64 uint_fast16_t sigZ;
65#else
66 int index;
67 uint16_t r0;
68 uint_fast16_t sigZ, rem;
69#endif
70 uint_fast16_t uiZ;
71 union ui16_f16 uZ;
72
73 /*------------------------------------------------------------------------
74 *------------------------------------------------------------------------*/
75 uA.f = a;
76 uiA = uA.ui;
77 signA = signF16UI( uiA );
78 expA = expF16UI( uiA );
79 sigA = fracF16UI( uiA );
80 uB.f = b;
81 uiB = uB.ui;
82 signB = signF16UI( uiB );
83 expB = expF16UI( uiB );
84 sigB = fracF16UI( uiB );
85 signZ = signA ^ signB;
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 if ( expA == 0x1F ) {
89 if ( sigA ) goto propagateNaN;
90 if ( expB == 0x1F ) {
91 if ( sigB ) goto propagateNaN;
92 goto invalid;
93 }
94 goto infinity;
95 }
96 if ( expB == 0x1F ) {
97 if ( sigB ) goto propagateNaN;
98 goto zero;
99 }
100 /*------------------------------------------------------------------------
101 *------------------------------------------------------------------------*/
102 if ( ! expB ) {
103 if ( ! sigB ) {
104 if ( ! (expA | sigA) ) goto invalid;
105 softfloat_raiseFlags( softfloat_flag_infinite );
106 goto infinity;
107 }
108 normExpSig = softfloat_normSubnormalF16Sig( sigB );
109 expB = normExpSig.exp;
110 sigB = normExpSig.sig;
111 }
112 if ( ! expA ) {
113 if ( ! sigA ) goto zero;
114 normExpSig = softfloat_normSubnormalF16Sig( sigA );
115 expA = normExpSig.exp;
116 sigA = normExpSig.sig;
117 }
118 /*------------------------------------------------------------------------
119 *------------------------------------------------------------------------*/
120 expZ = expA - expB + 0xE;
121 sigA |= 0x0400;
122 sigB |= 0x0400;
123#ifdef SOFTFLOAT_FAST_DIV32TO16
124 if ( sigA < sigB ) {
125 --expZ;
126 sig32A = (uint_fast32_t) sigA<<15;
127 } else {
128 sig32A = (uint_fast32_t) sigA<<14;
129 }
130 sigZ = sig32A / sigB;
131 if ( ! (sigZ & 7) ) sigZ |= ((uint_fast32_t) sigB * sigZ != sig32A);
132#else
133 if ( sigA < sigB ) {
134 --expZ;
135 sigA <<= 5;
136 } else {
137 sigA <<= 4;
138 }
139 index = sigB>>6 & 0xF;
140 r0 = softfloat_approxRecip_1k0s[index]
141 - (((uint_fast32_t) softfloat_approxRecip_1k1s[index]
142 * (sigB & 0x3F))
143 >>10);
144 sigZ = ((uint_fast32_t) sigA * r0)>>16;
145 rem = (sigA<<10) - sigZ * sigB;
146 sigZ += (rem * (uint_fast32_t) r0)>>26;
147 /*------------------------------------------------------------------------
148 *------------------------------------------------------------------------*/
149 ++sigZ;
150 if ( ! (sigZ & 7) ) {
151 sigZ &= ~1;
152 rem = (sigA<<10) - sigZ * sigB;
153 if ( rem & 0x8000 ) {
154 sigZ -= 2;
155 } else {
156 if ( rem ) sigZ |= 1;
157 }
158 }
159#endif
160 return softfloat_roundPackToF16( signZ, expZ, sigZ );
161 /*------------------------------------------------------------------------
162 *------------------------------------------------------------------------*/
163 propagateNaN:
164 uiZ = softfloat_propagateNaNF16UI( uiA, uiB );
165 goto uiZ;
166 /*------------------------------------------------------------------------
167 *------------------------------------------------------------------------*/
168 invalid:
169 softfloat_raiseFlags( softfloat_flag_invalid );
170 uiZ = defaultNaNF16UI;
171 goto uiZ;
172 /*------------------------------------------------------------------------
173 *------------------------------------------------------------------------*/
174 infinity:
175 uiZ = packToF16UI( signZ, 0x1F, 0 );
176 goto uiZ;
177 /*------------------------------------------------------------------------
178 *------------------------------------------------------------------------*/
179 zero:
180 uiZ = packToF16UI( signZ, 0, 0 );
181 uiZ:
182 uZ.ui = uiZ;
183 return uZ.f;
184
185}
186
deps/SoftFloat-3e/source/f16_eq.c deleted-66
...@@ -1,66 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool f16_eq( float16_t a, float16_t b )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 union ui16_f16 uB;
49 uint_fast16_t uiB;
50
51 uA.f = a;
52 uiA = uA.ui;
53 uB.f = b;
54 uiB = uB.ui;
55 if ( isNaNF16UI( uiA ) || isNaNF16UI( uiB ) ) {
56 if (
57 softfloat_isSigNaNF16UI( uiA ) || softfloat_isSigNaNF16UI( uiB )
58 ) {
59 softfloat_raiseFlags( softfloat_flag_invalid );
60 }
61 return false;
62 }
63 return (uiA == uiB) || ! (uint16_t) ((uiA | uiB)<<1);
64
65}
66
deps/SoftFloat-3e/source/f16_eq_signaling.c deleted-61
...@@ -1,61 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43bool f16_eq_signaling( float16_t a, float16_t b )
44{
45 union ui16_f16 uA;
46 uint_fast16_t uiA;
47 union ui16_f16 uB;
48 uint_fast16_t uiB;
49
50 uA.f = a;
51 uiA = uA.ui;
52 uB.f = b;
53 uiB = uB.ui;
54 if ( isNaNF16UI( uiA ) || isNaNF16UI( uiB ) ) {
55 softfloat_raiseFlags( softfloat_flag_invalid );
56 return false;
57 }
58 return (uiA == uiB) || ! (uint16_t) ((uiA | uiB)<<1);
59
60}
61
deps/SoftFloat-3e/source/f16_isSignalingNaN.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include "platform.h"
39#include "internals.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43bool f16_isSignalingNaN( float16_t a )
44{
45 union ui16_f16 uA;
46
47 uA.f = a;
48 return softfloat_isSigNaNF16UI( uA.ui );
49
50}
51
deps/SoftFloat-3e/source/f16_le.c deleted-66
...@@ -1,66 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43bool f16_le( float16_t a, float16_t b )
44{
45 union ui16_f16 uA;
46 uint_fast16_t uiA;
47 union ui16_f16 uB;
48 uint_fast16_t uiB;
49 bool signA, signB;
50
51 uA.f = a;
52 uiA = uA.ui;
53 uB.f = b;
54 uiB = uB.ui;
55 if ( isNaNF16UI( uiA ) || isNaNF16UI( uiB ) ) {
56 softfloat_raiseFlags( softfloat_flag_invalid );
57 return false;
58 }
59 signA = signF16UI( uiA );
60 signB = signF16UI( uiB );
61 return
62 (signA != signB) ? signA || ! (uint16_t) ((uiA | uiB)<<1)
63 : (uiA == uiB) || (signA ^ (uiA < uiB));
64
65}
66
deps/SoftFloat-3e/source/f16_le_quiet.c deleted-71
...@@ -1,71 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool f16_le_quiet( float16_t a, float16_t b )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 union ui16_f16 uB;
49 uint_fast16_t uiB;
50 bool signA, signB;
51
52 uA.f = a;
53 uiA = uA.ui;
54 uB.f = b;
55 uiB = uB.ui;
56 if ( isNaNF16UI( uiA ) || isNaNF16UI( uiB ) ) {
57 if (
58 softfloat_isSigNaNF16UI( uiA ) || softfloat_isSigNaNF16UI( uiB )
59 ) {
60 softfloat_raiseFlags( softfloat_flag_invalid );
61 }
62 return false;
63 }
64 signA = signF16UI( uiA );
65 signB = signF16UI( uiB );
66 return
67 (signA != signB) ? signA || ! (uint16_t) ((uiA | uiB)<<1)
68 : (uiA == uiB) || (signA ^ (uiA < uiB));
69
70}
71
deps/SoftFloat-3e/source/f16_lt.c deleted-66
...@@ -1,66 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43bool f16_lt( float16_t a, float16_t b )
44{
45 union ui16_f16 uA;
46 uint_fast16_t uiA;
47 union ui16_f16 uB;
48 uint_fast16_t uiB;
49 bool signA, signB;
50
51 uA.f = a;
52 uiA = uA.ui;
53 uB.f = b;
54 uiB = uB.ui;
55 if ( isNaNF16UI( uiA ) || isNaNF16UI( uiB ) ) {
56 softfloat_raiseFlags( softfloat_flag_invalid );
57 return false;
58 }
59 signA = signF16UI( uiA );
60 signB = signF16UI( uiB );
61 return
62 (signA != signB) ? signA && ((uint16_t) ((uiA | uiB)<<1) != 0)
63 : (uiA != uiB) && (signA ^ (uiA < uiB));
64
65}
66
deps/SoftFloat-3e/source/f16_lt_quiet.c deleted-71
...@@ -1,71 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool f16_lt_quiet( float16_t a, float16_t b )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 union ui16_f16 uB;
49 uint_fast16_t uiB;
50 bool signA, signB;
51
52 uA.f = a;
53 uiA = uA.ui;
54 uB.f = b;
55 uiB = uB.ui;
56 if ( isNaNF16UI( uiA ) || isNaNF16UI( uiB ) ) {
57 if (
58 softfloat_isSigNaNF16UI( uiA ) || softfloat_isSigNaNF16UI( uiB )
59 ) {
60 softfloat_raiseFlags( softfloat_flag_invalid );
61 }
62 return false;
63 }
64 signA = signF16UI( uiA );
65 signB = signF16UI( uiB );
66 return
67 (signA != signB) ? signA && ((uint16_t) ((uiA | uiB)<<1) != 0)
68 : (uiA != uiB) && (signA ^ (uiA < uiB));
69
70}
71
deps/SoftFloat-3e/source/f16_mul.c deleted-140
...@@ -1,140 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float16_t f16_mul( float16_t a, float16_t b )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 bool signA;
49 int_fast8_t expA;
50 uint_fast16_t sigA;
51 union ui16_f16 uB;
52 uint_fast16_t uiB;
53 bool signB;
54 int_fast8_t expB;
55 uint_fast16_t sigB;
56 bool signZ;
57 uint_fast16_t magBits;
58 struct exp8_sig16 normExpSig;
59 int_fast8_t expZ;
60 uint_fast32_t sig32Z;
61 uint_fast16_t sigZ, uiZ;
62 union ui16_f16 uZ;
63
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 uA.f = a;
67 uiA = uA.ui;
68 signA = signF16UI( uiA );
69 expA = expF16UI( uiA );
70 sigA = fracF16UI( uiA );
71 uB.f = b;
72 uiB = uB.ui;
73 signB = signF16UI( uiB );
74 expB = expF16UI( uiB );
75 sigB = fracF16UI( uiB );
76 signZ = signA ^ signB;
77 /*------------------------------------------------------------------------
78 *------------------------------------------------------------------------*/
79 if ( expA == 0x1F ) {
80 if ( sigA || ((expB == 0x1F) && sigB) ) goto propagateNaN;
81 magBits = expB | sigB;
82 goto infArg;
83 }
84 if ( expB == 0x1F ) {
85 if ( sigB ) goto propagateNaN;
86 magBits = expA | sigA;
87 goto infArg;
88 }
89 /*------------------------------------------------------------------------
90 *------------------------------------------------------------------------*/
91 if ( ! expA ) {
92 if ( ! sigA ) goto zero;
93 normExpSig = softfloat_normSubnormalF16Sig( sigA );
94 expA = normExpSig.exp;
95 sigA = normExpSig.sig;
96 }
97 if ( ! expB ) {
98 if ( ! sigB ) goto zero;
99 normExpSig = softfloat_normSubnormalF16Sig( sigB );
100 expB = normExpSig.exp;
101 sigB = normExpSig.sig;
102 }
103 /*------------------------------------------------------------------------
104 *------------------------------------------------------------------------*/
105 expZ = expA + expB - 0xF;
106 sigA = (sigA | 0x0400)<<4;
107 sigB = (sigB | 0x0400)<<5;
108 sig32Z = (uint_fast32_t) sigA * sigB;
109 sigZ = sig32Z>>16;
110 if ( sig32Z & 0xFFFF ) sigZ |= 1;
111 if ( sigZ < 0x4000 ) {
112 --expZ;
113 sigZ <<= 1;
114 }
115 return softfloat_roundPackToF16( signZ, expZ, sigZ );
116 /*------------------------------------------------------------------------
117 *------------------------------------------------------------------------*/
118 propagateNaN:
119 uiZ = softfloat_propagateNaNF16UI( uiA, uiB );
120 goto uiZ;
121 /*------------------------------------------------------------------------
122 *------------------------------------------------------------------------*/
123 infArg:
124 if ( ! magBits ) {
125 softfloat_raiseFlags( softfloat_flag_invalid );
126 uiZ = defaultNaNF16UI;
127 } else {
128 uiZ = packToF16UI( signZ, 0x1F, 0 );
129 }
130 goto uiZ;
131 /*------------------------------------------------------------------------
132 *------------------------------------------------------------------------*/
133 zero:
134 uiZ = packToF16UI( signZ, 0, 0 );
135 uiZ:
136 uZ.ui = uiZ;
137 return uZ.f;
138
139}
140
deps/SoftFloat-3e/source/f16_mulAdd.c deleted-60
...@@ -1,60 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float16_t f16_mulAdd( float16_t a, float16_t b, float16_t c )
43{
44 union ui16_f16 uA;
45 uint_fast16_t uiA;
46 union ui16_f16 uB;
47 uint_fast16_t uiB;
48 union ui16_f16 uC;
49 uint_fast16_t uiC;
50
51 uA.f = a;
52 uiA = uA.ui;
53 uB.f = b;
54 uiB = uB.ui;
55 uC.f = c;
56 uiC = uC.ui;
57 return softfloat_mulAddF16( uiA, uiB, uiC, 0 );
58
59}
60
deps/SoftFloat-3e/source/f16_rem.c deleted-171
...@@ -1,171 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float16_t f16_rem( float16_t a, float16_t b )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 bool signA;
49 int_fast8_t expA;
50 uint_fast16_t sigA;
51 union ui16_f16 uB;
52 uint_fast16_t uiB;
53 int_fast8_t expB;
54 uint_fast16_t sigB;
55 struct exp8_sig16 normExpSig;
56 uint16_t rem;
57 int_fast8_t expDiff;
58 uint_fast16_t q;
59 uint32_t recip32, q32;
60 uint16_t altRem, meanRem;
61 bool signRem;
62 uint_fast16_t uiZ;
63 union ui16_f16 uZ;
64
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 uA.f = a;
68 uiA = uA.ui;
69 signA = signF16UI( uiA );
70 expA = expF16UI( uiA );
71 sigA = fracF16UI( uiA );
72 uB.f = b;
73 uiB = uB.ui;
74 expB = expF16UI( uiB );
75 sigB = fracF16UI( uiB );
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 if ( expA == 0x1F ) {
79 if ( sigA || ((expB == 0x1F) && sigB) ) goto propagateNaN;
80 goto invalid;
81 }
82 if ( expB == 0x1F ) {
83 if ( sigB ) goto propagateNaN;
84 return a;
85 }
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 if ( ! expB ) {
89 if ( ! sigB ) goto invalid;
90 normExpSig = softfloat_normSubnormalF16Sig( sigB );
91 expB = normExpSig.exp;
92 sigB = normExpSig.sig;
93 }
94 if ( ! expA ) {
95 if ( ! sigA ) return a;
96 normExpSig = softfloat_normSubnormalF16Sig( sigA );
97 expA = normExpSig.exp;
98 sigA = normExpSig.sig;
99 }
100 /*------------------------------------------------------------------------
101 *------------------------------------------------------------------------*/
102 rem = sigA | 0x0400;
103 sigB |= 0x0400;
104 expDiff = expA - expB;
105 if ( expDiff < 1 ) {
106 if ( expDiff < -1 ) return a;
107 sigB <<= 3;
108 if ( expDiff ) {
109 rem <<= 2;
110 q = 0;
111 } else {
112 rem <<= 3;
113 q = (sigB <= rem);
114 if ( q ) rem -= sigB;
115 }
116 } else {
117 recip32 = softfloat_approxRecip32_1( (uint_fast32_t) sigB<<21 );
118 /*--------------------------------------------------------------------
119 | Changing the shift of `rem' here requires also changing the initial
120 | subtraction from `expDiff'.
121 *--------------------------------------------------------------------*/
122 rem <<= 4;
123 expDiff -= 31;
124 /*--------------------------------------------------------------------
125 | The scale of `sigB' affects how many bits are obtained during each
126 | cycle of the loop. Currently this is 29 bits per loop iteration,
127 | which is believed to be the maximum possible.
128 *--------------------------------------------------------------------*/
129 sigB <<= 3;
130 for (;;) {
131 q32 = (rem * (uint_fast64_t) recip32)>>16;
132 if ( expDiff < 0 ) break;
133 rem = -((uint_fast16_t) q32 * sigB);
134 expDiff -= 29;
135 }
136 /*--------------------------------------------------------------------
137 | (`expDiff' cannot be less than -30 here.)
138 *--------------------------------------------------------------------*/
139 q32 >>= ~expDiff & 31;
140 q = q32;
141 rem = (rem<<(expDiff + 30)) - q * sigB;
142 }
143 /*------------------------------------------------------------------------
144 *------------------------------------------------------------------------*/
145 do {
146 altRem = rem;
147 ++q;
148 rem -= sigB;
149 } while ( ! (rem & 0x8000) );
150 meanRem = rem + altRem;
151 if ( (meanRem & 0x8000) || (! meanRem && (q & 1)) ) rem = altRem;
152 signRem = signA;
153 if ( 0x8000 <= rem ) {
154 signRem = ! signRem;
155 rem = -rem;
156 }
157 return softfloat_normRoundPackToF16( signRem, expB, rem );
158 /*------------------------------------------------------------------------
159 *------------------------------------------------------------------------*/
160 propagateNaN:
161 uiZ = softfloat_propagateNaNF16UI( uiA, uiB );
162 goto uiZ;
163 invalid:
164 softfloat_raiseFlags( softfloat_flag_invalid );
165 uiZ = defaultNaNF16UI;
166 uiZ:
167 uZ.ui = uiZ;
168 return uZ.f;
169
170}
171
deps/SoftFloat-3e/source/f16_roundToInt.c deleted-120
...@@ -1,120 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float16_t f16_roundToInt( float16_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 int_fast8_t exp;
49 uint_fast16_t uiZ, lastBitMask, roundBitsMask;
50 union ui16_f16 uZ;
51
52 /*------------------------------------------------------------------------
53 *------------------------------------------------------------------------*/
54 uA.f = a;
55 uiA = uA.ui;
56 exp = expF16UI( uiA );
57 /*------------------------------------------------------------------------
58 *------------------------------------------------------------------------*/
59 if ( exp <= 0xE ) {
60 if ( !(uint16_t) (uiA<<1) ) return a;
61 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
62 uiZ = uiA & packToF16UI( 1, 0, 0 );
63 switch ( roundingMode ) {
64 case softfloat_round_near_even:
65 if ( !fracF16UI( uiA ) ) break;
66 case softfloat_round_near_maxMag:
67 if ( exp == 0xE ) uiZ |= packToF16UI( 0, 0xF, 0 );
68 break;
69 case softfloat_round_min:
70 if ( uiZ ) uiZ = packToF16UI( 1, 0xF, 0 );
71 break;
72 case softfloat_round_max:
73 if ( !uiZ ) uiZ = packToF16UI( 0, 0xF, 0 );
74 break;
75#ifdef SOFTFLOAT_ROUND_ODD
76 case softfloat_round_odd:
77 uiZ |= packToF16UI( 0, 0xF, 0 );
78 break;
79#endif
80 }
81 goto uiZ;
82 }
83 /*------------------------------------------------------------------------
84 *------------------------------------------------------------------------*/
85 if ( 0x19 <= exp ) {
86 if ( (exp == 0x1F) && fracF16UI( uiA ) ) {
87 uiZ = softfloat_propagateNaNF16UI( uiA, 0 );
88 goto uiZ;
89 }
90 return a;
91 }
92 /*------------------------------------------------------------------------
93 *------------------------------------------------------------------------*/
94 uiZ = uiA;
95 lastBitMask = (uint_fast16_t) 1<<(0x19 - exp);
96 roundBitsMask = lastBitMask - 1;
97 if ( roundingMode == softfloat_round_near_maxMag ) {
98 uiZ += lastBitMask>>1;
99 } else if ( roundingMode == softfloat_round_near_even ) {
100 uiZ += lastBitMask>>1;
101 if ( !(uiZ & roundBitsMask) ) uiZ &= ~lastBitMask;
102 } else if (
103 roundingMode
104 == (signF16UI( uiZ ) ? softfloat_round_min : softfloat_round_max)
105 ) {
106 uiZ += roundBitsMask;
107 }
108 uiZ &= ~roundBitsMask;
109 if ( uiZ != uiA ) {
110#ifdef SOFTFLOAT_ROUND_ODD
111 if ( roundingMode == softfloat_round_odd ) uiZ |= lastBitMask;
112#endif
113 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
114 }
115 uiZ:
116 uZ.ui = uiZ;
117 return uZ.f;
118
119}
120
deps/SoftFloat-3e/source/f16_sqrt.c deleted-136
...@@ -1,136 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44extern const uint16_t softfloat_approxRecipSqrt_1k0s[];
45extern const uint16_t softfloat_approxRecipSqrt_1k1s[];
46
47float16_t f16_sqrt( float16_t a )
48{
49 union ui16_f16 uA;
50 uint_fast16_t uiA;
51 bool signA;
52 int_fast8_t expA;
53 uint_fast16_t sigA, uiZ;
54 struct exp8_sig16 normExpSig;
55 int_fast8_t expZ;
56 int index;
57 uint_fast16_t r0;
58 uint_fast32_t ESqrR0;
59 uint16_t sigma0;
60 uint_fast16_t recipSqrt16, sigZ, shiftedSigZ;
61 uint16_t negRem;
62 union ui16_f16 uZ;
63
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 uA.f = a;
67 uiA = uA.ui;
68 signA = signF16UI( uiA );
69 expA = expF16UI( uiA );
70 sigA = fracF16UI( uiA );
71 /*------------------------------------------------------------------------
72 *------------------------------------------------------------------------*/
73 if ( expA == 0x1F ) {
74 if ( sigA ) {
75 uiZ = softfloat_propagateNaNF16UI( uiA, 0 );
76 goto uiZ;
77 }
78 if ( ! signA ) return a;
79 goto invalid;
80 }
81 /*------------------------------------------------------------------------
82 *------------------------------------------------------------------------*/
83 if ( signA ) {
84 if ( ! (expA | sigA) ) return a;
85 goto invalid;
86 }
87 /*------------------------------------------------------------------------
88 *------------------------------------------------------------------------*/
89 if ( ! expA ) {
90 if ( ! sigA ) return a;
91 normExpSig = softfloat_normSubnormalF16Sig( sigA );
92 expA = normExpSig.exp;
93 sigA = normExpSig.sig;
94 }
95 /*------------------------------------------------------------------------
96 *------------------------------------------------------------------------*/
97 expZ = ((expA - 0xF)>>1) + 0xE;
98 expA &= 1;
99 sigA |= 0x0400;
100 index = (sigA>>6 & 0xE) + expA;
101 r0 = softfloat_approxRecipSqrt_1k0s[index]
102 - (((uint_fast32_t) softfloat_approxRecipSqrt_1k1s[index]
103 * (sigA & 0x7F))
104 >>11);
105 ESqrR0 = ((uint_fast32_t) r0 * r0)>>1;
106 if ( expA ) ESqrR0 >>= 1;
107 sigma0 = ~(uint_fast16_t) ((ESqrR0 * sigA)>>16);
108 recipSqrt16 = r0 + (((uint_fast32_t) r0 * sigma0)>>25);
109 if ( ! (recipSqrt16 & 0x8000) ) recipSqrt16 = 0x8000;
110 sigZ = ((uint_fast32_t) (sigA<<5) * recipSqrt16)>>16;
111 if ( expA ) sigZ >>= 1;
112 /*------------------------------------------------------------------------
113 *------------------------------------------------------------------------*/
114 ++sigZ;
115 if ( ! (sigZ & 7) ) {
116 shiftedSigZ = sigZ>>1;
117 negRem = shiftedSigZ * shiftedSigZ;
118 sigZ &= ~1;
119 if ( negRem & 0x8000 ) {
120 sigZ |= 1;
121 } else {
122 if ( negRem ) --sigZ;
123 }
124 }
125 return softfloat_roundPackToF16( 0, expZ, sigZ );
126 /*------------------------------------------------------------------------
127 *------------------------------------------------------------------------*/
128 invalid:
129 softfloat_raiseFlags( softfloat_flag_invalid );
130 uiZ = defaultNaNF16UI;
131 uiZ:
132 uZ.ui = uiZ;
133 return uZ.f;
134
135}
136
deps/SoftFloat-3e/source/f16_sub.c deleted-70
...@@ -1,70 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float16_t f16_sub( float16_t a, float16_t b )
44{
45 union ui16_f16 uA;
46 uint_fast16_t uiA;
47 union ui16_f16 uB;
48 uint_fast16_t uiB;
49#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1)
50 float16_t (*magsFuncPtr)( uint_fast16_t, uint_fast16_t );
51#endif
52
53 uA.f = a;
54 uiA = uA.ui;
55 uB.f = b;
56 uiB = uB.ui;
57#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
58 if ( signF16UI( uiA ^ uiB ) ) {
59 return softfloat_addMagsF16( uiA, uiB );
60 } else {
61 return softfloat_subMagsF16( uiA, uiB );
62 }
63#else
64 magsFuncPtr =
65 signF16UI( uiA ^ uiB ) ? softfloat_addMagsF16 : softfloat_subMagsF16;
66 return (*magsFuncPtr)( uiA, uiB );
67#endif
68
69}
70
deps/SoftFloat-3e/source/f16_to_extF80.c deleted-101
...@@ -1,101 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44extFloat80_t f16_to_extF80( float16_t a )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 bool sign;
49 int_fast8_t exp;
50 uint_fast16_t frac;
51 struct commonNaN commonNaN;
52 struct uint128 uiZ;
53 uint_fast16_t uiZ64;
54 uint_fast64_t uiZ0;
55 struct exp8_sig16 normExpSig;
56 union { struct extFloat80M s; extFloat80_t f; } uZ;
57
58 /*------------------------------------------------------------------------
59 *------------------------------------------------------------------------*/
60 uA.f = a;
61 uiA = uA.ui;
62 sign = signF16UI( uiA );
63 exp = expF16UI( uiA );
64 frac = fracF16UI( uiA );
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 if ( exp == 0x1F ) {
68 if ( frac ) {
69 softfloat_f16UIToCommonNaN( uiA, &commonNaN );
70 uiZ = softfloat_commonNaNToExtF80UI( &commonNaN );
71 uiZ64 = uiZ.v64;
72 uiZ0 = uiZ.v0;
73 } else {
74 uiZ64 = packToExtF80UI64( sign, 0x7FFF );
75 uiZ0 = UINT64_C( 0x8000000000000000 );
76 }
77 goto uiZ;
78 }
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 if ( ! exp ) {
82 if ( ! frac ) {
83 uiZ64 = packToExtF80UI64( sign, 0 );
84 uiZ0 = 0;
85 goto uiZ;
86 }
87 normExpSig = softfloat_normSubnormalF16Sig( frac );
88 exp = normExpSig.exp;
89 frac = normExpSig.sig;
90 }
91 /*------------------------------------------------------------------------
92 *------------------------------------------------------------------------*/
93 uiZ64 = packToExtF80UI64( sign, exp + 0x3FF0 );
94 uiZ0 = (uint_fast64_t) (frac | 0x0400)<<53;
95 uiZ:
96 uZ.s.signExp = uiZ64;
97 uZ.s.signif = uiZ0;
98 return uZ.f;
99
100}
101
deps/SoftFloat-3e/source/f16_to_extF80M.c deleted-111
...@@ -1,111 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void f16_to_extF80M( float16_t a, extFloat80_t *zPtr )
47{
48
49 *zPtr = f16_to_extF80( a );
50
51}
52
53#else
54
55void f16_to_extF80M( float16_t a, extFloat80_t *zPtr )
56{
57 struct extFloat80M *zSPtr;
58 union ui16_f16 uA;
59 uint16_t uiA;
60 bool sign;
61 int_fast8_t exp;
62 uint16_t frac;
63 struct commonNaN commonNaN;
64 uint_fast16_t uiZ64;
65 uint32_t uiZ32;
66 struct exp8_sig16 normExpSig;
67
68 /*------------------------------------------------------------------------
69 *------------------------------------------------------------------------*/
70 zSPtr = (struct extFloat80M *) zPtr;
71 uA.f = a;
72 uiA = uA.ui;
73 sign = signF16UI( uiA );
74 exp = expF16UI( uiA );
75 frac = fracF16UI( uiA );
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 if ( exp == 0x1F ) {
79 if ( frac ) {
80 softfloat_f16UIToCommonNaN( uiA, &commonNaN );
81 softfloat_commonNaNToExtF80M( &commonNaN, zSPtr );
82 return;
83 }
84 uiZ64 = packToExtF80UI64( sign, 0x7FFF );
85 uiZ32 = 0x80000000;
86 goto uiZ;
87 }
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 if ( ! exp ) {
91 if ( ! frac ) {
92 uiZ64 = packToExtF80UI64( sign, 0 );
93 uiZ32 = 0;
94 goto uiZ;
95 }
96 normExpSig = softfloat_normSubnormalF16Sig( frac );
97 exp = normExpSig.exp;
98 frac = normExpSig.sig;
99 }
100 /*------------------------------------------------------------------------
101 *------------------------------------------------------------------------*/
102 uiZ64 = packToExtF80UI64( sign, exp + 0x3FF0 );
103 uiZ32 = 0x80000000 | (uint32_t) frac<<21;
104 uiZ:
105 zSPtr->signExp = uiZ64;
106 zSPtr->signif = (uint64_t) uiZ32<<32;
107
108}
109
110#endif
111
deps/SoftFloat-3e/source/f16_to_f128.c deleted-96
...@@ -1,96 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float128_t f16_to_f128( float16_t a )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 bool sign;
49 int_fast8_t exp;
50 uint_fast16_t frac;
51 struct commonNaN commonNaN;
52 struct uint128 uiZ;
53 struct exp8_sig16 normExpSig;
54 union ui128_f128 uZ;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 uA.f = a;
59 uiA = uA.ui;
60 sign = signF16UI( uiA );
61 exp = expF16UI( uiA );
62 frac = fracF16UI( uiA );
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 if ( exp == 0x1F ) {
66 if ( frac ) {
67 softfloat_f16UIToCommonNaN( uiA, &commonNaN );
68 uiZ = softfloat_commonNaNToF128UI( &commonNaN );
69 } else {
70 uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 );
71 uiZ.v0 = 0;
72 }
73 goto uiZ;
74 }
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 if ( ! exp ) {
78 if ( ! frac ) {
79 uiZ.v64 = packToF128UI64( sign, 0, 0 );
80 uiZ.v0 = 0;
81 goto uiZ;
82 }
83 normExpSig = softfloat_normSubnormalF16Sig( frac );
84 exp = normExpSig.exp - 1;
85 frac = normExpSig.sig;
86 }
87 /*------------------------------------------------------------------------
88 *------------------------------------------------------------------------*/
89 uiZ.v64 = packToF128UI64( sign, exp + 0x3FF0, (uint_fast64_t) frac<<38 );
90 uiZ.v0 = 0;
91 uiZ:
92 uZ.ui = uiZ;
93 return uZ.f;
94
95}
96
deps/SoftFloat-3e/source/f16_to_f128M.c deleted-111
...@@ -1,111 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void f16_to_f128M( float16_t a, float128_t *zPtr )
47{
48
49 *zPtr = f16_to_f128( a );
50
51}
52
53#else
54
55void f16_to_f128M( float16_t a, float128_t *zPtr )
56{
57 uint32_t *zWPtr;
58 union ui16_f16 uA;
59 uint16_t uiA;
60 bool sign;
61 int_fast8_t exp;
62 uint16_t frac;
63 struct commonNaN commonNaN;
64 uint32_t uiZ96;
65 struct exp8_sig16 normExpSig;
66
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 zWPtr = (uint32_t *) zPtr;
70 /*------------------------------------------------------------------------
71 *------------------------------------------------------------------------*/
72 uA.f = a;
73 uiA = uA.ui;
74 sign = signF16UI( uiA );
75 exp = expF16UI( uiA );
76 frac = fracF16UI( uiA );
77 /*------------------------------------------------------------------------
78 *------------------------------------------------------------------------*/
79 if ( exp == 0x1F ) {
80 if ( frac ) {
81 softfloat_f16UIToCommonNaN( uiA, &commonNaN );
82 softfloat_commonNaNToF128M( &commonNaN, zWPtr );
83 return;
84 }
85 uiZ96 = packToF128UI96( sign, 0x7FFF, 0 );
86 goto uiZ;
87 }
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 if ( ! exp ) {
91 if ( ! frac ) {
92 uiZ96 = packToF128UI96( sign, 0, 0 );
93 goto uiZ;
94 }
95 normExpSig = softfloat_normSubnormalF16Sig( frac );
96 exp = normExpSig.exp - 1;
97 frac = normExpSig.sig;
98 }
99 /*------------------------------------------------------------------------
100 *------------------------------------------------------------------------*/
101 uiZ96 = packToF128UI96( sign, exp + 0x3FF0, (uint32_t) frac<<6 );
102 uiZ:
103 zWPtr[indexWord( 4, 3 )] = uiZ96;
104 zWPtr[indexWord( 4, 2 )] = 0;
105 zWPtr[indexWord( 4, 1 )] = 0;
106 zWPtr[indexWord( 4, 0 )] = 0;
107
108}
109
110#endif
111
deps/SoftFloat-3e/source/f16_to_f32.c deleted-93
...@@ -1,93 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float32_t f16_to_f32( float16_t a )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 bool sign;
49 int_fast8_t exp;
50 uint_fast16_t frac;
51 struct commonNaN commonNaN;
52 uint_fast32_t uiZ;
53 struct exp8_sig16 normExpSig;
54 union ui32_f32 uZ;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 uA.f = a;
59 uiA = uA.ui;
60 sign = signF16UI( uiA );
61 exp = expF16UI( uiA );
62 frac = fracF16UI( uiA );
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 if ( exp == 0x1F ) {
66 if ( frac ) {
67 softfloat_f16UIToCommonNaN( uiA, &commonNaN );
68 uiZ = softfloat_commonNaNToF32UI( &commonNaN );
69 } else {
70 uiZ = packToF32UI( sign, 0xFF, 0 );
71 }
72 goto uiZ;
73 }
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( ! exp ) {
77 if ( ! frac ) {
78 uiZ = packToF32UI( sign, 0, 0 );
79 goto uiZ;
80 }
81 normExpSig = softfloat_normSubnormalF16Sig( frac );
82 exp = normExpSig.exp - 1;
83 frac = normExpSig.sig;
84 }
85 /*------------------------------------------------------------------------
86 *------------------------------------------------------------------------*/
87 uiZ = packToF32UI( sign, exp + 0x70, (uint_fast32_t) frac<<13 );
88 uiZ:
89 uZ.ui = uiZ;
90 return uZ.f;
91
92}
93
deps/SoftFloat-3e/source/f16_to_f64.c deleted-93
...@@ -1,93 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float64_t f16_to_f64( float16_t a )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 bool sign;
49 int_fast8_t exp;
50 uint_fast16_t frac;
51 struct commonNaN commonNaN;
52 uint_fast64_t uiZ;
53 struct exp8_sig16 normExpSig;
54 union ui64_f64 uZ;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 uA.f = a;
59 uiA = uA.ui;
60 sign = signF16UI( uiA );
61 exp = expF16UI( uiA );
62 frac = fracF16UI( uiA );
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 if ( exp == 0x1F ) {
66 if ( frac ) {
67 softfloat_f16UIToCommonNaN( uiA, &commonNaN );
68 uiZ = softfloat_commonNaNToF64UI( &commonNaN );
69 } else {
70 uiZ = packToF64UI( sign, 0x7FF, 0 );
71 }
72 goto uiZ;
73 }
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( ! exp ) {
77 if ( ! frac ) {
78 uiZ = packToF64UI( sign, 0, 0 );
79 goto uiZ;
80 }
81 normExpSig = softfloat_normSubnormalF16Sig( frac );
82 exp = normExpSig.exp - 1;
83 frac = normExpSig.sig;
84 }
85 /*------------------------------------------------------------------------
86 *------------------------------------------------------------------------*/
87 uiZ = packToF64UI( sign, exp + 0x3F0, (uint_fast64_t) frac<<42 );
88 uiZ:
89 uZ.ui = uiZ;
90 return uZ.f;
91
92}
93
deps/SoftFloat-3e/source/f16_to_i32.c deleted-87
...@@ -1,87 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast32_t f16_to_i32( float16_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 bool sign;
49 int_fast8_t exp;
50 uint_fast16_t frac;
51 int_fast32_t sig32;
52 int_fast8_t shiftDist;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 sign = signF16UI( uiA );
59 exp = expF16UI( uiA );
60 frac = fracF16UI( uiA );
61 /*------------------------------------------------------------------------
62 *------------------------------------------------------------------------*/
63 if ( exp == 0x1F ) {
64 softfloat_raiseFlags( softfloat_flag_invalid );
65 return
66 frac ? i32_fromNaN
67 : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sig32 = frac;
72 if ( exp ) {
73 sig32 |= 0x0400;
74 shiftDist = exp - 0x19;
75 if ( 0 <= shiftDist ) {
76 sig32 <<= shiftDist;
77 return sign ? -sig32 : sig32;
78 }
79 shiftDist = exp - 0x0D;
80 if ( 0 < shiftDist ) sig32 <<= shiftDist;
81 }
82 return
83 softfloat_roundToI32(
84 sign, (uint_fast32_t) sig32, roundingMode, exact );
85
86}
87
deps/SoftFloat-3e/source/f16_to_i32_r_minMag.c deleted-88
...@@ -1,88 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast32_t f16_to_i32_r_minMag( float16_t a, bool exact )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 int_fast8_t exp;
49 uint_fast16_t frac;
50 int_fast8_t shiftDist;
51 bool sign;
52 int_fast32_t alignedSig;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 exp = expF16UI( uiA );
59 frac = fracF16UI( uiA );
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = exp - 0x0F;
63 if ( shiftDist < 0 ) {
64 if ( exact && (exp | frac) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signF16UI( uiA );
72 if ( exp == 0x1F ) {
73 softfloat_raiseFlags( softfloat_flag_invalid );
74 return
75 (exp == 0x1F) && frac ? i32_fromNaN
76 : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
77 }
78 /*------------------------------------------------------------------------
79 *------------------------------------------------------------------------*/
80 alignedSig = (int_fast32_t) (frac | 0x0400)<<shiftDist;
81 if ( exact && (alignedSig & 0x3FF) ) {
82 softfloat_exceptionFlags |= softfloat_flag_inexact;
83 }
84 alignedSig >>= 10;
85 return sign ? -alignedSig : alignedSig;
86
87}
88
deps/SoftFloat-3e/source/f16_to_i64.c deleted-87
...@@ -1,87 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast64_t f16_to_i64( float16_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 bool sign;
49 int_fast8_t exp;
50 uint_fast16_t frac;
51 int_fast32_t sig32;
52 int_fast8_t shiftDist;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 sign = signF16UI( uiA );
59 exp = expF16UI( uiA );
60 frac = fracF16UI( uiA );
61 /*------------------------------------------------------------------------
62 *------------------------------------------------------------------------*/
63 if ( exp == 0x1F ) {
64 softfloat_raiseFlags( softfloat_flag_invalid );
65 return
66 frac ? i64_fromNaN
67 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sig32 = frac;
72 if ( exp ) {
73 sig32 |= 0x0400;
74 shiftDist = exp - 0x19;
75 if ( 0 <= shiftDist ) {
76 sig32 <<= shiftDist;
77 return sign ? -sig32 : sig32;
78 }
79 shiftDist = exp - 0x0D;
80 if ( 0 < shiftDist ) sig32 <<= shiftDist;
81 }
82 return
83 softfloat_roundToI32(
84 sign, (uint_fast32_t) sig32, roundingMode, exact );
85
86}
87
deps/SoftFloat-3e/source/f16_to_i64_r_minMag.c deleted-88
...@@ -1,88 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast64_t f16_to_i64_r_minMag( float16_t a, bool exact )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 int_fast8_t exp;
49 uint_fast16_t frac;
50 int_fast8_t shiftDist;
51 bool sign;
52 int_fast32_t alignedSig;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 exp = expF16UI( uiA );
59 frac = fracF16UI( uiA );
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = exp - 0x0F;
63 if ( shiftDist < 0 ) {
64 if ( exact && (exp | frac) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signF16UI( uiA );
72 if ( exp == 0x1F ) {
73 softfloat_raiseFlags( softfloat_flag_invalid );
74 return
75 (exp == 0x1F) && frac ? i64_fromNaN
76 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
77 }
78 /*------------------------------------------------------------------------
79 *------------------------------------------------------------------------*/
80 alignedSig = (int_fast32_t) (frac | 0x0400)<<shiftDist;
81 if ( exact && (alignedSig & 0x3FF) ) {
82 softfloat_exceptionFlags |= softfloat_flag_inexact;
83 }
84 alignedSig >>= 10;
85 return sign ? -alignedSig : alignedSig;
86
87}
88
deps/SoftFloat-3e/source/f16_to_ui32.c deleted-84
...@@ -1,84 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast32_t f16_to_ui32( float16_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 bool sign;
49 int_fast8_t exp;
50 uint_fast16_t frac;
51 uint_fast32_t sig32;
52 int_fast8_t shiftDist;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 sign = signF16UI( uiA );
59 exp = expF16UI( uiA );
60 frac = fracF16UI( uiA );
61 /*------------------------------------------------------------------------
62 *------------------------------------------------------------------------*/
63 if ( exp == 0x1F ) {
64 softfloat_raiseFlags( softfloat_flag_invalid );
65 return
66 frac ? ui32_fromNaN
67 : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sig32 = frac;
72 if ( exp ) {
73 sig32 |= 0x0400;
74 shiftDist = exp - 0x19;
75 if ( (0 <= shiftDist) && ! sign ) {
76 return sig32<<shiftDist;
77 }
78 shiftDist = exp - 0x0D;
79 if ( 0 < shiftDist ) sig32 <<= shiftDist;
80 }
81 return softfloat_roundToUI32( sign, sig32, roundingMode, exact );
82
83}
84
deps/SoftFloat-3e/source/f16_to_ui32_r_minMag.c deleted-87
...@@ -1,87 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast32_t f16_to_ui32_r_minMag( float16_t a, bool exact )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 int_fast8_t exp;
49 uint_fast16_t frac;
50 int_fast8_t shiftDist;
51 bool sign;
52 uint_fast32_t alignedSig;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 exp = expF16UI( uiA );
59 frac = fracF16UI( uiA );
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = exp - 0x0F;
63 if ( shiftDist < 0 ) {
64 if ( exact && (exp | frac) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signF16UI( uiA );
72 if ( sign || (exp == 0x1F) ) {
73 softfloat_raiseFlags( softfloat_flag_invalid );
74 return
75 (exp == 0x1F) && frac ? ui32_fromNaN
76 : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
77 }
78 /*------------------------------------------------------------------------
79 *------------------------------------------------------------------------*/
80 alignedSig = (uint_fast32_t) (frac | 0x0400)<<shiftDist;
81 if ( exact && (alignedSig & 0x3FF) ) {
82 softfloat_exceptionFlags |= softfloat_flag_inexact;
83 }
84 return alignedSig>>10;
85
86}
87
deps/SoftFloat-3e/source/f16_to_ui64.c deleted-96
...@@ -1,96 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast64_t f16_to_ui64( float16_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 bool sign;
49 int_fast8_t exp;
50 uint_fast16_t frac;
51 uint_fast32_t sig32;
52 int_fast8_t shiftDist;
53#ifndef SOFTFLOAT_FAST_INT64
54 uint32_t extSig[3];
55#endif
56
57 /*------------------------------------------------------------------------
58 *------------------------------------------------------------------------*/
59 uA.f = a;
60 uiA = uA.ui;
61 sign = signF16UI( uiA );
62 exp = expF16UI( uiA );
63 frac = fracF16UI( uiA );
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 if ( exp == 0x1F ) {
67 softfloat_raiseFlags( softfloat_flag_invalid );
68 return
69 frac ? ui64_fromNaN
70 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
71 }
72 /*------------------------------------------------------------------------
73 *------------------------------------------------------------------------*/
74 sig32 = frac;
75 if ( exp ) {
76 sig32 |= 0x0400;
77 shiftDist = exp - 0x19;
78 if ( (0 <= shiftDist) && ! sign ) {
79 return sig32<<shiftDist;
80 }
81 shiftDist = exp - 0x0D;
82 if ( 0 < shiftDist ) sig32 <<= shiftDist;
83 }
84#ifdef SOFTFLOAT_FAST_INT64
85 return
86 softfloat_roundToUI64(
87 sign, sig32>>12, (uint_fast64_t) sig32<<52, roundingMode, exact );
88#else
89 extSig[indexWord( 3, 2 )] = 0;
90 extSig[indexWord( 3, 1 )] = sig32>>12;
91 extSig[indexWord( 3, 0 )] = sig32<<20;
92 return softfloat_roundMToUI64( sign, extSig, roundingMode, exact );
93#endif
94
95}
96
deps/SoftFloat-3e/source/f16_to_ui64_r_minMag.c deleted-87
...@@ -1,87 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast64_t f16_to_ui64_r_minMag( float16_t a, bool exact )
45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 int_fast8_t exp;
49 uint_fast16_t frac;
50 int_fast8_t shiftDist;
51 bool sign;
52 uint_fast32_t alignedSig;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 exp = expF16UI( uiA );
59 frac = fracF16UI( uiA );
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = exp - 0x0F;
63 if ( shiftDist < 0 ) {
64 if ( exact && (exp | frac) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signF16UI( uiA );
72 if ( sign || (exp == 0x1F) ) {
73 softfloat_raiseFlags( softfloat_flag_invalid );
74 return
75 (exp == 0x1F) && frac ? ui64_fromNaN
76 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
77 }
78 /*------------------------------------------------------------------------
79 *------------------------------------------------------------------------*/
80 alignedSig = (uint_fast32_t) (frac | 0x0400)<<shiftDist;
81 if ( exact && (alignedSig & 0x3FF) ) {
82 softfloat_exceptionFlags |= softfloat_flag_inexact;
83 }
84 return alignedSig>>10;
85
86}
87
deps/SoftFloat-3e/source/f32_add.c deleted-70
...@@ -1,70 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float32_t f32_add( float32_t a, float32_t b )
44{
45 union ui32_f32 uA;
46 uint_fast32_t uiA;
47 union ui32_f32 uB;
48 uint_fast32_t uiB;
49#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1)
50 float32_t (*magsFuncPtr)( uint_fast32_t, uint_fast32_t );
51#endif
52
53 uA.f = a;
54 uiA = uA.ui;
55 uB.f = b;
56 uiB = uB.ui;
57#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
58 if ( signF32UI( uiA ^ uiB ) ) {
59 return softfloat_subMagsF32( uiA, uiB );
60 } else {
61 return softfloat_addMagsF32( uiA, uiB );
62 }
63#else
64 magsFuncPtr =
65 signF32UI( uiA ^ uiB ) ? softfloat_subMagsF32 : softfloat_addMagsF32;
66 return (*magsFuncPtr)( uiA, uiB );
67#endif
68
69}
70
deps/SoftFloat-3e/source/f32_div.c deleted-180
...@@ -1,180 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float32_t f32_div( float32_t a, float32_t b )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 bool signA;
49 int_fast16_t expA;
50 uint_fast32_t sigA;
51 union ui32_f32 uB;
52 uint_fast32_t uiB;
53 bool signB;
54 int_fast16_t expB;
55 uint_fast32_t sigB;
56 bool signZ;
57 struct exp16_sig32 normExpSig;
58 int_fast16_t expZ;
59#ifdef SOFTFLOAT_FAST_DIV64TO32
60 uint_fast64_t sig64A;
61 uint_fast32_t sigZ;
62#else
63 uint_fast32_t sigZ;
64 uint_fast64_t rem;
65#endif
66 uint_fast32_t uiZ;
67 union ui32_f32 uZ;
68
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 uA.f = a;
72 uiA = uA.ui;
73 signA = signF32UI( uiA );
74 expA = expF32UI( uiA );
75 sigA = fracF32UI( uiA );
76 uB.f = b;
77 uiB = uB.ui;
78 signB = signF32UI( uiB );
79 expB = expF32UI( uiB );
80 sigB = fracF32UI( uiB );
81 signZ = signA ^ signB;
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( expA == 0xFF ) {
85 if ( sigA ) goto propagateNaN;
86 if ( expB == 0xFF ) {
87 if ( sigB ) goto propagateNaN;
88 goto invalid;
89 }
90 goto infinity;
91 }
92 if ( expB == 0xFF ) {
93 if ( sigB ) goto propagateNaN;
94 goto zero;
95 }
96 /*------------------------------------------------------------------------
97 *------------------------------------------------------------------------*/
98 if ( ! expB ) {
99 if ( ! sigB ) {
100 if ( ! (expA | sigA) ) goto invalid;
101 softfloat_raiseFlags( softfloat_flag_infinite );
102 goto infinity;
103 }
104 normExpSig = softfloat_normSubnormalF32Sig( sigB );
105 expB = normExpSig.exp;
106 sigB = normExpSig.sig;
107 }
108 if ( ! expA ) {
109 if ( ! sigA ) goto zero;
110 normExpSig = softfloat_normSubnormalF32Sig( sigA );
111 expA = normExpSig.exp;
112 sigA = normExpSig.sig;
113 }
114 /*------------------------------------------------------------------------
115 *------------------------------------------------------------------------*/
116 expZ = expA - expB + 0x7E;
117 sigA |= 0x00800000;
118 sigB |= 0x00800000;
119#ifdef SOFTFLOAT_FAST_DIV64TO32
120 if ( sigA < sigB ) {
121 --expZ;
122 sig64A = (uint_fast64_t) sigA<<31;
123 } else {
124 sig64A = (uint_fast64_t) sigA<<30;
125 }
126 sigZ = sig64A / sigB;
127 if ( ! (sigZ & 0x3F) ) sigZ |= ((uint_fast64_t) sigB * sigZ != sig64A);
128#else
129 if ( sigA < sigB ) {
130 --expZ;
131 sigA <<= 8;
132 } else {
133 sigA <<= 7;
134 }
135 sigB <<= 8;
136 sigZ = ((uint_fast64_t) sigA * softfloat_approxRecip32_1( sigB ))>>32;
137 /*------------------------------------------------------------------------
138 *------------------------------------------------------------------------*/
139 sigZ += 2;
140 if ( (sigZ & 0x3F) < 2 ) {
141 sigZ &= ~3;
142#ifdef SOFTFLOAT_FAST_INT64
143 rem = ((uint_fast64_t) sigA<<31) - (uint_fast64_t) sigZ * sigB;
144#else
145 rem = ((uint_fast64_t) sigA<<32) - (uint_fast64_t) (sigZ<<1) * sigB;
146#endif
147 if ( rem & UINT64_C( 0x8000000000000000 ) ) {
148 sigZ -= 4;
149 } else {
150 if ( rem ) sigZ |= 1;
151 }
152 }
153#endif
154 return softfloat_roundPackToF32( signZ, expZ, sigZ );
155 /*------------------------------------------------------------------------
156 *------------------------------------------------------------------------*/
157 propagateNaN:
158 uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
159 goto uiZ;
160 /*------------------------------------------------------------------------
161 *------------------------------------------------------------------------*/
162 invalid:
163 softfloat_raiseFlags( softfloat_flag_invalid );
164 uiZ = defaultNaNF32UI;
165 goto uiZ;
166 /*------------------------------------------------------------------------
167 *------------------------------------------------------------------------*/
168 infinity:
169 uiZ = packToF32UI( signZ, 0xFF, 0 );
170 goto uiZ;
171 /*------------------------------------------------------------------------
172 *------------------------------------------------------------------------*/
173 zero:
174 uiZ = packToF32UI( signZ, 0, 0 );
175 uiZ:
176 uZ.ui = uiZ;
177 return uZ.f;
178
179}
180
deps/SoftFloat-3e/source/f32_eq.c deleted-66
...@@ -1,66 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool f32_eq( float32_t a, float32_t b )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 union ui32_f32 uB;
49 uint_fast32_t uiB;
50
51 uA.f = a;
52 uiA = uA.ui;
53 uB.f = b;
54 uiB = uB.ui;
55 if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) {
56 if (
57 softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB )
58 ) {
59 softfloat_raiseFlags( softfloat_flag_invalid );
60 }
61 return false;
62 }
63 return (uiA == uiB) || ! (uint32_t) ((uiA | uiB)<<1);
64
65}
66
deps/SoftFloat-3e/source/f32_eq_signaling.c deleted-61
...@@ -1,61 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43bool f32_eq_signaling( float32_t a, float32_t b )
44{
45 union ui32_f32 uA;
46 uint_fast32_t uiA;
47 union ui32_f32 uB;
48 uint_fast32_t uiB;
49
50 uA.f = a;
51 uiA = uA.ui;
52 uB.f = b;
53 uiB = uB.ui;
54 if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) {
55 softfloat_raiseFlags( softfloat_flag_invalid );
56 return false;
57 }
58 return (uiA == uiB) || ! (uint32_t) ((uiA | uiB)<<1);
59
60}
61
deps/SoftFloat-3e/source/f32_isSignalingNaN.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include "platform.h"
39#include "internals.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43bool f32_isSignalingNaN( float32_t a )
44{
45 union ui32_f32 uA;
46
47 uA.f = a;
48 return softfloat_isSigNaNF32UI( uA.ui );
49
50}
51
deps/SoftFloat-3e/source/f32_le.c deleted-66
...@@ -1,66 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43bool f32_le( float32_t a, float32_t b )
44{
45 union ui32_f32 uA;
46 uint_fast32_t uiA;
47 union ui32_f32 uB;
48 uint_fast32_t uiB;
49 bool signA, signB;
50
51 uA.f = a;
52 uiA = uA.ui;
53 uB.f = b;
54 uiB = uB.ui;
55 if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) {
56 softfloat_raiseFlags( softfloat_flag_invalid );
57 return false;
58 }
59 signA = signF32UI( uiA );
60 signB = signF32UI( uiB );
61 return
62 (signA != signB) ? signA || ! (uint32_t) ((uiA | uiB)<<1)
63 : (uiA == uiB) || (signA ^ (uiA < uiB));
64
65}
66
deps/SoftFloat-3e/source/f32_le_quiet.c deleted-71
...@@ -1,71 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool f32_le_quiet( float32_t a, float32_t b )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 union ui32_f32 uB;
49 uint_fast32_t uiB;
50 bool signA, signB;
51
52 uA.f = a;
53 uiA = uA.ui;
54 uB.f = b;
55 uiB = uB.ui;
56 if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) {
57 if (
58 softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB )
59 ) {
60 softfloat_raiseFlags( softfloat_flag_invalid );
61 }
62 return false;
63 }
64 signA = signF32UI( uiA );
65 signB = signF32UI( uiB );
66 return
67 (signA != signB) ? signA || ! (uint32_t) ((uiA | uiB)<<1)
68 : (uiA == uiB) || (signA ^ (uiA < uiB));
69
70}
71
deps/SoftFloat-3e/source/f32_lt.c deleted-66
...@@ -1,66 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43bool f32_lt( float32_t a, float32_t b )
44{
45 union ui32_f32 uA;
46 uint_fast32_t uiA;
47 union ui32_f32 uB;
48 uint_fast32_t uiB;
49 bool signA, signB;
50
51 uA.f = a;
52 uiA = uA.ui;
53 uB.f = b;
54 uiB = uB.ui;
55 if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) {
56 softfloat_raiseFlags( softfloat_flag_invalid );
57 return false;
58 }
59 signA = signF32UI( uiA );
60 signB = signF32UI( uiB );
61 return
62 (signA != signB) ? signA && ((uint32_t) ((uiA | uiB)<<1) != 0)
63 : (uiA != uiB) && (signA ^ (uiA < uiB));
64
65}
66
deps/SoftFloat-3e/source/f32_lt_quiet.c deleted-71
...@@ -1,71 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool f32_lt_quiet( float32_t a, float32_t b )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 union ui32_f32 uB;
49 uint_fast32_t uiB;
50 bool signA, signB;
51
52 uA.f = a;
53 uiA = uA.ui;
54 uB.f = b;
55 uiB = uB.ui;
56 if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) {
57 if (
58 softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB )
59 ) {
60 softfloat_raiseFlags( softfloat_flag_invalid );
61 }
62 return false;
63 }
64 signA = signF32UI( uiA );
65 signB = signF32UI( uiB );
66 return
67 (signA != signB) ? signA && ((uint32_t) ((uiA | uiB)<<1) != 0)
68 : (uiA != uiB) && (signA ^ (uiA < uiB));
69
70}
71
deps/SoftFloat-3e/source/f32_mul.c deleted-137
...@@ -1,137 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float32_t f32_mul( float32_t a, float32_t b )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 bool signA;
49 int_fast16_t expA;
50 uint_fast32_t sigA;
51 union ui32_f32 uB;
52 uint_fast32_t uiB;
53 bool signB;
54 int_fast16_t expB;
55 uint_fast32_t sigB;
56 bool signZ;
57 uint_fast32_t magBits;
58 struct exp16_sig32 normExpSig;
59 int_fast16_t expZ;
60 uint_fast32_t sigZ, uiZ;
61 union ui32_f32 uZ;
62
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 uA.f = a;
66 uiA = uA.ui;
67 signA = signF32UI( uiA );
68 expA = expF32UI( uiA );
69 sigA = fracF32UI( uiA );
70 uB.f = b;
71 uiB = uB.ui;
72 signB = signF32UI( uiB );
73 expB = expF32UI( uiB );
74 sigB = fracF32UI( uiB );
75 signZ = signA ^ signB;
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 if ( expA == 0xFF ) {
79 if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN;
80 magBits = expB | sigB;
81 goto infArg;
82 }
83 if ( expB == 0xFF ) {
84 if ( sigB ) goto propagateNaN;
85 magBits = expA | sigA;
86 goto infArg;
87 }
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 if ( ! expA ) {
91 if ( ! sigA ) goto zero;
92 normExpSig = softfloat_normSubnormalF32Sig( sigA );
93 expA = normExpSig.exp;
94 sigA = normExpSig.sig;
95 }
96 if ( ! expB ) {
97 if ( ! sigB ) goto zero;
98 normExpSig = softfloat_normSubnormalF32Sig( sigB );
99 expB = normExpSig.exp;
100 sigB = normExpSig.sig;
101 }
102 /*------------------------------------------------------------------------
103 *------------------------------------------------------------------------*/
104 expZ = expA + expB - 0x7F;
105 sigA = (sigA | 0x00800000)<<7;
106 sigB = (sigB | 0x00800000)<<8;
107 sigZ = softfloat_shortShiftRightJam64( (uint_fast64_t) sigA * sigB, 32 );
108 if ( sigZ < 0x40000000 ) {
109 --expZ;
110 sigZ <<= 1;
111 }
112 return softfloat_roundPackToF32( signZ, expZ, sigZ );
113 /*------------------------------------------------------------------------
114 *------------------------------------------------------------------------*/
115 propagateNaN:
116 uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
117 goto uiZ;
118 /*------------------------------------------------------------------------
119 *------------------------------------------------------------------------*/
120 infArg:
121 if ( ! magBits ) {
122 softfloat_raiseFlags( softfloat_flag_invalid );
123 uiZ = defaultNaNF32UI;
124 } else {
125 uiZ = packToF32UI( signZ, 0xFF, 0 );
126 }
127 goto uiZ;
128 /*------------------------------------------------------------------------
129 *------------------------------------------------------------------------*/
130 zero:
131 uiZ = packToF32UI( signZ, 0, 0 );
132 uiZ:
133 uZ.ui = uiZ;
134 return uZ.f;
135
136}
137
deps/SoftFloat-3e/source/f32_mulAdd.c deleted-60
...@@ -1,60 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float32_t f32_mulAdd( float32_t a, float32_t b, float32_t c )
43{
44 union ui32_f32 uA;
45 uint_fast32_t uiA;
46 union ui32_f32 uB;
47 uint_fast32_t uiB;
48 union ui32_f32 uC;
49 uint_fast32_t uiC;
50
51 uA.f = a;
52 uiA = uA.ui;
53 uB.f = b;
54 uiB = uB.ui;
55 uC.f = c;
56 uiC = uC.ui;
57 return softfloat_mulAddF32( uiA, uiB, uiC, 0 );
58
59}
60
deps/SoftFloat-3e/source/f32_rem.c deleted-168
...@@ -1,168 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float32_t f32_rem( float32_t a, float32_t b )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 bool signA;
49 int_fast16_t expA;
50 uint_fast32_t sigA;
51 union ui32_f32 uB;
52 uint_fast32_t uiB;
53 int_fast16_t expB;
54 uint_fast32_t sigB;
55 struct exp16_sig32 normExpSig;
56 uint32_t rem;
57 int_fast16_t expDiff;
58 uint32_t q, recip32, altRem, meanRem;
59 bool signRem;
60 uint_fast32_t uiZ;
61 union ui32_f32 uZ;
62
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 uA.f = a;
66 uiA = uA.ui;
67 signA = signF32UI( uiA );
68 expA = expF32UI( uiA );
69 sigA = fracF32UI( uiA );
70 uB.f = b;
71 uiB = uB.ui;
72 expB = expF32UI( uiB );
73 sigB = fracF32UI( uiB );
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( expA == 0xFF ) {
77 if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN;
78 goto invalid;
79 }
80 if ( expB == 0xFF ) {
81 if ( sigB ) goto propagateNaN;
82 return a;
83 }
84 /*------------------------------------------------------------------------
85 *------------------------------------------------------------------------*/
86 if ( ! expB ) {
87 if ( ! sigB ) goto invalid;
88 normExpSig = softfloat_normSubnormalF32Sig( sigB );
89 expB = normExpSig.exp;
90 sigB = normExpSig.sig;
91 }
92 if ( ! expA ) {
93 if ( ! sigA ) return a;
94 normExpSig = softfloat_normSubnormalF32Sig( sigA );
95 expA = normExpSig.exp;
96 sigA = normExpSig.sig;
97 }
98 /*------------------------------------------------------------------------
99 *------------------------------------------------------------------------*/
100 rem = sigA | 0x00800000;
101 sigB |= 0x00800000;
102 expDiff = expA - expB;
103 if ( expDiff < 1 ) {
104 if ( expDiff < -1 ) return a;
105 sigB <<= 6;
106 if ( expDiff ) {
107 rem <<= 5;
108 q = 0;
109 } else {
110 rem <<= 6;
111 q = (sigB <= rem);
112 if ( q ) rem -= sigB;
113 }
114 } else {
115 recip32 = softfloat_approxRecip32_1( sigB<<8 );
116 /*--------------------------------------------------------------------
117 | Changing the shift of `rem' here requires also changing the initial
118 | subtraction from `expDiff'.
119 *--------------------------------------------------------------------*/
120 rem <<= 7;
121 expDiff -= 31;
122 /*--------------------------------------------------------------------
123 | The scale of `sigB' affects how many bits are obtained during each
124 | cycle of the loop. Currently this is 29 bits per loop iteration,
125 | which is believed to be the maximum possible.
126 *--------------------------------------------------------------------*/
127 sigB <<= 6;
128 for (;;) {
129 q = (rem * (uint_fast64_t) recip32)>>32;
130 if ( expDiff < 0 ) break;
131 rem = -(q * (uint32_t) sigB);
132 expDiff -= 29;
133 }
134 /*--------------------------------------------------------------------
135 | (`expDiff' cannot be less than -30 here.)
136 *--------------------------------------------------------------------*/
137 q >>= ~expDiff & 31;
138 rem = (rem<<(expDiff + 30)) - q * (uint32_t) sigB;
139 }
140 /*------------------------------------------------------------------------
141 *------------------------------------------------------------------------*/
142 do {
143 altRem = rem;
144 ++q;
145 rem -= sigB;
146 } while ( ! (rem & 0x80000000) );
147 meanRem = rem + altRem;
148 if ( (meanRem & 0x80000000) || (! meanRem && (q & 1)) ) rem = altRem;
149 signRem = signA;
150 if ( 0x80000000 <= rem ) {
151 signRem = ! signRem;
152 rem = -rem;
153 }
154 return softfloat_normRoundPackToF32( signRem, expB, rem );
155 /*------------------------------------------------------------------------
156 *------------------------------------------------------------------------*/
157 propagateNaN:
158 uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
159 goto uiZ;
160 invalid:
161 softfloat_raiseFlags( softfloat_flag_invalid );
162 uiZ = defaultNaNF32UI;
163 uiZ:
164 uZ.ui = uiZ;
165 return uZ.f;
166
167}
168
deps/SoftFloat-3e/source/f32_roundToInt.c deleted-120
...@@ -1,120 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float32_t f32_roundToInt( float32_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 int_fast16_t exp;
49 uint_fast32_t uiZ, lastBitMask, roundBitsMask;
50 union ui32_f32 uZ;
51
52 /*------------------------------------------------------------------------
53 *------------------------------------------------------------------------*/
54 uA.f = a;
55 uiA = uA.ui;
56 exp = expF32UI( uiA );
57 /*------------------------------------------------------------------------
58 *------------------------------------------------------------------------*/
59 if ( exp <= 0x7E ) {
60 if ( !(uint32_t) (uiA<<1) ) return a;
61 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
62 uiZ = uiA & packToF32UI( 1, 0, 0 );
63 switch ( roundingMode ) {
64 case softfloat_round_near_even:
65 if ( !fracF32UI( uiA ) ) break;
66 case softfloat_round_near_maxMag:
67 if ( exp == 0x7E ) uiZ |= packToF32UI( 0, 0x7F, 0 );
68 break;
69 case softfloat_round_min:
70 if ( uiZ ) uiZ = packToF32UI( 1, 0x7F, 0 );
71 break;
72 case softfloat_round_max:
73 if ( !uiZ ) uiZ = packToF32UI( 0, 0x7F, 0 );
74 break;
75#ifdef SOFTFLOAT_ROUND_ODD
76 case softfloat_round_odd:
77 uiZ |= packToF32UI( 0, 0x7F, 0 );
78 break;
79#endif
80 }
81 goto uiZ;
82 }
83 /*------------------------------------------------------------------------
84 *------------------------------------------------------------------------*/
85 if ( 0x96 <= exp ) {
86 if ( (exp == 0xFF) && fracF32UI( uiA ) ) {
87 uiZ = softfloat_propagateNaNF32UI( uiA, 0 );
88 goto uiZ;
89 }
90 return a;
91 }
92 /*------------------------------------------------------------------------
93 *------------------------------------------------------------------------*/
94 uiZ = uiA;
95 lastBitMask = (uint_fast32_t) 1<<(0x96 - exp);
96 roundBitsMask = lastBitMask - 1;
97 if ( roundingMode == softfloat_round_near_maxMag ) {
98 uiZ += lastBitMask>>1;
99 } else if ( roundingMode == softfloat_round_near_even ) {
100 uiZ += lastBitMask>>1;
101 if ( !(uiZ & roundBitsMask) ) uiZ &= ~lastBitMask;
102 } else if (
103 roundingMode
104 == (signF32UI( uiZ ) ? softfloat_round_min : softfloat_round_max)
105 ) {
106 uiZ += roundBitsMask;
107 }
108 uiZ &= ~roundBitsMask;
109 if ( uiZ != uiA ) {
110#ifdef SOFTFLOAT_ROUND_ODD
111 if ( roundingMode == softfloat_round_odd ) uiZ |= lastBitMask;
112#endif
113 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
114 }
115 uiZ:
116 uZ.ui = uiZ;
117 return uZ.f;
118
119}
120
deps/SoftFloat-3e/source/f32_sqrt.c deleted-121
...@@ -1,121 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float32_t f32_sqrt( float32_t a )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 bool signA;
49 int_fast16_t expA;
50 uint_fast32_t sigA, uiZ;
51 struct exp16_sig32 normExpSig;
52 int_fast16_t expZ;
53 uint_fast32_t sigZ, shiftedSigZ;
54 uint32_t negRem;
55 union ui32_f32 uZ;
56
57 /*------------------------------------------------------------------------
58 *------------------------------------------------------------------------*/
59 uA.f = a;
60 uiA = uA.ui;
61 signA = signF32UI( uiA );
62 expA = expF32UI( uiA );
63 sigA = fracF32UI( uiA );
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 if ( expA == 0xFF ) {
67 if ( sigA ) {
68 uiZ = softfloat_propagateNaNF32UI( uiA, 0 );
69 goto uiZ;
70 }
71 if ( ! signA ) return a;
72 goto invalid;
73 }
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( signA ) {
77 if ( ! (expA | sigA) ) return a;
78 goto invalid;
79 }
80 /*------------------------------------------------------------------------
81 *------------------------------------------------------------------------*/
82 if ( ! expA ) {
83 if ( ! sigA ) return a;
84 normExpSig = softfloat_normSubnormalF32Sig( sigA );
85 expA = normExpSig.exp;
86 sigA = normExpSig.sig;
87 }
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 expZ = ((expA - 0x7F)>>1) + 0x7E;
91 expA &= 1;
92 sigA = (sigA | 0x00800000)<<8;
93 sigZ =
94 ((uint_fast64_t) sigA * softfloat_approxRecipSqrt32_1( expA, sigA ))
95 >>32;
96 if ( expA ) sigZ >>= 1;
97 /*------------------------------------------------------------------------
98 *------------------------------------------------------------------------*/
99 sigZ += 2;
100 if ( (sigZ & 0x3F) < 2 ) {
101 shiftedSigZ = sigZ>>2;
102 negRem = shiftedSigZ * shiftedSigZ;
103 sigZ &= ~3;
104 if ( negRem & 0x80000000 ) {
105 sigZ |= 1;
106 } else {
107 if ( negRem ) --sigZ;
108 }
109 }
110 return softfloat_roundPackToF32( 0, expZ, sigZ );
111 /*------------------------------------------------------------------------
112 *------------------------------------------------------------------------*/
113 invalid:
114 softfloat_raiseFlags( softfloat_flag_invalid );
115 uiZ = defaultNaNF32UI;
116 uiZ:
117 uZ.ui = uiZ;
118 return uZ.f;
119
120}
121
deps/SoftFloat-3e/source/f32_sub.c deleted-70
...@@ -1,70 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float32_t f32_sub( float32_t a, float32_t b )
44{
45 union ui32_f32 uA;
46 uint_fast32_t uiA;
47 union ui32_f32 uB;
48 uint_fast32_t uiB;
49#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1)
50 float32_t (*magsFuncPtr)( uint_fast32_t, uint_fast32_t );
51#endif
52
53 uA.f = a;
54 uiA = uA.ui;
55 uB.f = b;
56 uiB = uB.ui;
57#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
58 if ( signF32UI( uiA ^ uiB ) ) {
59 return softfloat_addMagsF32( uiA, uiB );
60 } else {
61 return softfloat_subMagsF32( uiA, uiB );
62 }
63#else
64 magsFuncPtr =
65 signF32UI( uiA ^ uiB ) ? softfloat_addMagsF32 : softfloat_subMagsF32;
66 return (*magsFuncPtr)( uiA, uiB );
67#endif
68
69}
70
deps/SoftFloat-3e/source/f32_to_extF80.c deleted-101
...@@ -1,101 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44extFloat80_t f32_to_extF80( float32_t a )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast32_t frac;
51 struct commonNaN commonNaN;
52 struct uint128 uiZ;
53 uint_fast16_t uiZ64;
54 uint_fast64_t uiZ0;
55 struct exp16_sig32 normExpSig;
56 union { struct extFloat80M s; extFloat80_t f; } uZ;
57
58 /*------------------------------------------------------------------------
59 *------------------------------------------------------------------------*/
60 uA.f = a;
61 uiA = uA.ui;
62 sign = signF32UI( uiA );
63 exp = expF32UI( uiA );
64 frac = fracF32UI( uiA );
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 if ( exp == 0xFF ) {
68 if ( frac ) {
69 softfloat_f32UIToCommonNaN( uiA, &commonNaN );
70 uiZ = softfloat_commonNaNToExtF80UI( &commonNaN );
71 uiZ64 = uiZ.v64;
72 uiZ0 = uiZ.v0;
73 } else {
74 uiZ64 = packToExtF80UI64( sign, 0x7FFF );
75 uiZ0 = UINT64_C( 0x8000000000000000 );
76 }
77 goto uiZ;
78 }
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 if ( ! exp ) {
82 if ( ! frac ) {
83 uiZ64 = packToExtF80UI64( sign, 0 );
84 uiZ0 = 0;
85 goto uiZ;
86 }
87 normExpSig = softfloat_normSubnormalF32Sig( frac );
88 exp = normExpSig.exp;
89 frac = normExpSig.sig;
90 }
91 /*------------------------------------------------------------------------
92 *------------------------------------------------------------------------*/
93 uiZ64 = packToExtF80UI64( sign, exp + 0x3F80 );
94 uiZ0 = (uint_fast64_t) (frac | 0x00800000)<<40;
95 uiZ:
96 uZ.s.signExp = uiZ64;
97 uZ.s.signif = uiZ0;
98 return uZ.f;
99
100}
101
deps/SoftFloat-3e/source/f32_to_extF80M.c deleted-111
...@@ -1,111 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void f32_to_extF80M( float32_t a, extFloat80_t *zPtr )
47{
48
49 *zPtr = f32_to_extF80( a );
50
51}
52
53#else
54
55void f32_to_extF80M( float32_t a, extFloat80_t *zPtr )
56{
57 struct extFloat80M *zSPtr;
58 union ui32_f32 uA;
59 uint32_t uiA;
60 bool sign;
61 int_fast16_t exp;
62 uint32_t frac;
63 struct commonNaN commonNaN;
64 uint_fast16_t uiZ64;
65 uint32_t uiZ32;
66 struct exp16_sig32 normExpSig;
67
68 /*------------------------------------------------------------------------
69 *------------------------------------------------------------------------*/
70 zSPtr = (struct extFloat80M *) zPtr;
71 uA.f = a;
72 uiA = uA.ui;
73 sign = signF32UI( uiA );
74 exp = expF32UI( uiA );
75 frac = fracF32UI( uiA );
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 if ( exp == 0xFF ) {
79 if ( frac ) {
80 softfloat_f32UIToCommonNaN( uiA, &commonNaN );
81 softfloat_commonNaNToExtF80M( &commonNaN, zSPtr );
82 return;
83 }
84 uiZ64 = packToExtF80UI64( sign, 0x7FFF );
85 uiZ32 = 0x80000000;
86 goto uiZ;
87 }
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 if ( ! exp ) {
91 if ( ! frac ) {
92 uiZ64 = packToExtF80UI64( sign, 0 );
93 uiZ32 = 0;
94 goto uiZ;
95 }
96 normExpSig = softfloat_normSubnormalF32Sig( frac );
97 exp = normExpSig.exp;
98 frac = normExpSig.sig;
99 }
100 /*------------------------------------------------------------------------
101 *------------------------------------------------------------------------*/
102 uiZ64 = packToExtF80UI64( sign, exp + 0x3F80 );
103 uiZ32 = 0x80000000 | (uint32_t) frac<<8;
104 uiZ:
105 zSPtr->signExp = uiZ64;
106 zSPtr->signif = (uint64_t) uiZ32<<32;
107
108}
109
110#endif
111
deps/SoftFloat-3e/source/f32_to_f128.c deleted-96
...@@ -1,96 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float128_t f32_to_f128( float32_t a )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast32_t frac;
51 struct commonNaN commonNaN;
52 struct uint128 uiZ;
53 struct exp16_sig32 normExpSig;
54 union ui128_f128 uZ;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 uA.f = a;
59 uiA = uA.ui;
60 sign = signF32UI( uiA );
61 exp = expF32UI( uiA );
62 frac = fracF32UI( uiA );
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 if ( exp == 0xFF ) {
66 if ( frac ) {
67 softfloat_f32UIToCommonNaN( uiA, &commonNaN );
68 uiZ = softfloat_commonNaNToF128UI( &commonNaN );
69 } else {
70 uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 );
71 uiZ.v0 = 0;
72 }
73 goto uiZ;
74 }
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 if ( ! exp ) {
78 if ( ! frac ) {
79 uiZ.v64 = packToF128UI64( sign, 0, 0 );
80 uiZ.v0 = 0;
81 goto uiZ;
82 }
83 normExpSig = softfloat_normSubnormalF32Sig( frac );
84 exp = normExpSig.exp - 1;
85 frac = normExpSig.sig;
86 }
87 /*------------------------------------------------------------------------
88 *------------------------------------------------------------------------*/
89 uiZ.v64 = packToF128UI64( sign, exp + 0x3F80, (uint_fast64_t) frac<<25 );
90 uiZ.v0 = 0;
91 uiZ:
92 uZ.ui = uiZ;
93 return uZ.f;
94
95}
96
deps/SoftFloat-3e/source/f32_to_f128M.c deleted-115
...@@ -1,115 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void f32_to_f128M( float32_t a, float128_t *zPtr )
47{
48
49 *zPtr = f32_to_f128( a );
50
51}
52
53#else
54
55void f32_to_f128M( float32_t a, float128_t *zPtr )
56{
57 uint32_t *zWPtr;
58 union ui32_f32 uA;
59 uint32_t uiA;
60 bool sign;
61 int_fast16_t exp;
62 uint32_t frac, uiZ64;
63 struct commonNaN commonNaN;
64 uint32_t uiZ96;
65 struct exp16_sig32 normExpSig;
66 uint64_t frac64;
67
68 /*------------------------------------------------------------------------
69 *------------------------------------------------------------------------*/
70 zWPtr = (uint32_t *) zPtr;
71 /*------------------------------------------------------------------------
72 *------------------------------------------------------------------------*/
73 uA.f = a;
74 uiA = uA.ui;
75 sign = signF32UI( uiA );
76 exp = expF32UI( uiA );
77 frac = fracF32UI( uiA );
78 /*------------------------------------------------------------------------
79 *------------------------------------------------------------------------*/
80 uiZ64 = 0;
81 if ( exp == 0xFF ) {
82 if ( frac ) {
83 softfloat_f32UIToCommonNaN( uiA, &commonNaN );
84 softfloat_commonNaNToF128M( &commonNaN, zWPtr );
85 return;
86 }
87 uiZ96 = packToF128UI96( sign, 0x7FFF, 0 );
88 goto uiZ;
89 }
90 /*------------------------------------------------------------------------
91 *------------------------------------------------------------------------*/
92 if ( ! exp ) {
93 if ( ! frac ) {
94 uiZ96 = packToF128UI96( sign, 0, 0 );
95 goto uiZ;
96 }
97 normExpSig = softfloat_normSubnormalF32Sig( frac );
98 exp = normExpSig.exp - 1;
99 frac = normExpSig.sig;
100 }
101 /*------------------------------------------------------------------------
102 *------------------------------------------------------------------------*/
103 frac64 = (uint64_t) frac<<25;
104 uiZ96 = packToF128UI96( sign, exp + 0x3F80, frac64>>32 );
105 uiZ64 = frac64;
106 uiZ:
107 zWPtr[indexWord( 4, 3 )] = uiZ96;
108 zWPtr[indexWord( 4, 2 )] = uiZ64;
109 zWPtr[indexWord( 4, 1 )] = 0;
110 zWPtr[indexWord( 4, 0 )] = 0;
111
112}
113
114#endif
115
deps/SoftFloat-3e/source/f32_to_f16.c deleted-88
...@@ -1,88 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float16_t f32_to_f16( float32_t a )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast32_t frac;
51 struct commonNaN commonNaN;
52 uint_fast16_t uiZ, frac16;
53 union ui16_f16 uZ;
54
55 /*------------------------------------------------------------------------
56 *------------------------------------------------------------------------*/
57 uA.f = a;
58 uiA = uA.ui;
59 sign = signF32UI( uiA );
60 exp = expF32UI( uiA );
61 frac = fracF32UI( uiA );
62 /*------------------------------------------------------------------------
63 *------------------------------------------------------------------------*/
64 if ( exp == 0xFF ) {
65 if ( frac ) {
66 softfloat_f32UIToCommonNaN( uiA, &commonNaN );
67 uiZ = softfloat_commonNaNToF16UI( &commonNaN );
68 } else {
69 uiZ = packToF16UI( sign, 0x1F, 0 );
70 }
71 goto uiZ;
72 }
73 /*------------------------------------------------------------------------
74 *------------------------------------------------------------------------*/
75 frac16 = frac>>9 | ((frac & 0x1FF) != 0);
76 if ( ! (exp | frac16) ) {
77 uiZ = packToF16UI( sign, 0, 0 );
78 goto uiZ;
79 }
80 /*------------------------------------------------------------------------
81 *------------------------------------------------------------------------*/
82 return softfloat_roundPackToF16( sign, exp - 0x71, frac16 | 0x4000 );
83 uiZ:
84 uZ.ui = uiZ;
85 return uZ.f;
86
87}
88
deps/SoftFloat-3e/source/f32_to_f64.c deleted-93
...@@ -1,93 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float64_t f32_to_f64( float32_t a )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast32_t frac;
51 struct commonNaN commonNaN;
52 uint_fast64_t uiZ;
53 struct exp16_sig32 normExpSig;
54 union ui64_f64 uZ;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 uA.f = a;
59 uiA = uA.ui;
60 sign = signF32UI( uiA );
61 exp = expF32UI( uiA );
62 frac = fracF32UI( uiA );
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 if ( exp == 0xFF ) {
66 if ( frac ) {
67 softfloat_f32UIToCommonNaN( uiA, &commonNaN );
68 uiZ = softfloat_commonNaNToF64UI( &commonNaN );
69 } else {
70 uiZ = packToF64UI( sign, 0x7FF, 0 );
71 }
72 goto uiZ;
73 }
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( ! exp ) {
77 if ( ! frac ) {
78 uiZ = packToF64UI( sign, 0, 0 );
79 goto uiZ;
80 }
81 normExpSig = softfloat_normSubnormalF32Sig( frac );
82 exp = normExpSig.exp - 1;
83 frac = normExpSig.sig;
84 }
85 /*------------------------------------------------------------------------
86 *------------------------------------------------------------------------*/
87 uiZ = packToF64UI( sign, exp + 0x380, (uint_fast64_t) frac<<29 );
88 uiZ:
89 uZ.ui = uiZ;
90 return uZ.f;
91
92}
93
deps/SoftFloat-3e/source/f32_to_i32.c deleted-84
...@@ -1,84 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast32_t f32_to_i32( float32_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast32_t sig;
51 uint_fast64_t sig64;
52 int_fast16_t shiftDist;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 sign = signF32UI( uiA );
59 exp = expF32UI( uiA );
60 sig = fracF32UI( uiA );
61 /*------------------------------------------------------------------------
62 *------------------------------------------------------------------------*/
63#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
64 if ( (exp == 0xFF) && sig ) {
65#if (i32_fromNaN == i32_fromPosOverflow)
66 sign = 0;
67#elif (i32_fromNaN == i32_fromNegOverflow)
68 sign = 1;
69#else
70 softfloat_raiseFlags( softfloat_flag_invalid );
71 return i32_fromNaN;
72#endif
73 }
74#endif
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 if ( exp ) sig |= 0x00800000;
78 sig64 = (uint_fast64_t) sig<<32;
79 shiftDist = 0xAA - exp;
80 if ( 0 < shiftDist ) sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
81 return softfloat_roundToI32( sign, sig64, roundingMode, exact );
82
83}
84
deps/SoftFloat-3e/source/f32_to_i32_r_minMag.c deleted-89
...@@ -1,89 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast32_t f32_to_i32_r_minMag( float32_t a, bool exact )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 int_fast16_t exp;
49 uint_fast32_t sig;
50 int_fast16_t shiftDist;
51 bool sign;
52 int_fast32_t absZ;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 exp = expF32UI( uiA );
59 sig = fracF32UI( uiA );
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = 0x9E - exp;
63 if ( 32 <= shiftDist ) {
64 if ( exact && (exp | sig) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signF32UI( uiA );
72 if ( shiftDist <= 0 ) {
73 if ( uiA == packToF32UI( 1, 0x9E, 0 ) ) return -0x7FFFFFFF - 1;
74 softfloat_raiseFlags( softfloat_flag_invalid );
75 return
76 (exp == 0xFF) && sig ? i32_fromNaN
77 : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
78 }
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 sig = (sig | 0x00800000)<<8;
82 absZ = sig>>shiftDist;
83 if ( exact && ((uint_fast32_t) absZ<<shiftDist != sig) ) {
84 softfloat_exceptionFlags |= softfloat_flag_inexact;
85 }
86 return sign ? -absZ : absZ;
87
88}
89
deps/SoftFloat-3e/source/f32_to_i64.c deleted-96
...@@ -1,96 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast64_t f32_to_i64( float32_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast32_t sig;
51 int_fast16_t shiftDist;
52#ifdef SOFTFLOAT_FAST_INT64
53 uint_fast64_t sig64, extra;
54 struct uint64_extra sig64Extra;
55#else
56 uint32_t extSig[3];
57#endif
58
59 /*------------------------------------------------------------------------
60 *------------------------------------------------------------------------*/
61 uA.f = a;
62 uiA = uA.ui;
63 sign = signF32UI( uiA );
64 exp = expF32UI( uiA );
65 sig = fracF32UI( uiA );
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 shiftDist = 0xBE - exp;
69 if ( shiftDist < 0 ) {
70 softfloat_raiseFlags( softfloat_flag_invalid );
71 return
72 (exp == 0xFF) && sig ? i64_fromNaN
73 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
74 }
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 if ( exp ) sig |= 0x00800000;
78#ifdef SOFTFLOAT_FAST_INT64
79 sig64 = (uint_fast64_t) sig<<40;
80 extra = 0;
81 if ( shiftDist ) {
82 sig64Extra = softfloat_shiftRightJam64Extra( sig64, 0, shiftDist );
83 sig64 = sig64Extra.v;
84 extra = sig64Extra.extra;
85 }
86 return softfloat_roundToI64( sign, sig64, extra, roundingMode, exact );
87#else
88 extSig[indexWord( 3, 2 )] = sig<<8;
89 extSig[indexWord( 3, 1 )] = 0;
90 extSig[indexWord( 3, 0 )] = 0;
91 if ( shiftDist ) softfloat_shiftRightJam96M( extSig, shiftDist, extSig );
92 return softfloat_roundMToI64( sign, extSig, roundingMode, exact );
93#endif
94
95}
96
deps/SoftFloat-3e/source/f32_to_i64_r_minMag.c deleted-94
...@@ -1,94 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast64_t f32_to_i64_r_minMag( float32_t a, bool exact )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 int_fast16_t exp;
49 uint_fast32_t sig;
50 int_fast16_t shiftDist;
51 bool sign;
52 uint_fast64_t sig64;
53 int_fast64_t absZ;
54
55 /*------------------------------------------------------------------------
56 *------------------------------------------------------------------------*/
57 uA.f = a;
58 uiA = uA.ui;
59 exp = expF32UI( uiA );
60 sig = fracF32UI( uiA );
61 /*------------------------------------------------------------------------
62 *------------------------------------------------------------------------*/
63 shiftDist = 0xBE - exp;
64 if ( 64 <= shiftDist ) {
65 if ( exact && (exp | sig) ) {
66 softfloat_exceptionFlags |= softfloat_flag_inexact;
67 }
68 return 0;
69 }
70 /*------------------------------------------------------------------------
71 *------------------------------------------------------------------------*/
72 sign = signF32UI( uiA );
73 if ( shiftDist <= 0 ) {
74 if ( uiA == packToF32UI( 1, 0xBE, 0 ) ) {
75 return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1;
76 }
77 softfloat_raiseFlags( softfloat_flag_invalid );
78 return
79 (exp == 0xFF) && sig ? i64_fromNaN
80 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
81 }
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 sig |= 0x00800000;
85 sig64 = (uint_fast64_t) sig<<40;
86 absZ = sig64>>shiftDist;
87 shiftDist = 40 - shiftDist;
88 if ( exact && (shiftDist < 0) && (uint32_t) (sig<<(shiftDist & 31)) ) {
89 softfloat_exceptionFlags |= softfloat_flag_inexact;
90 }
91 return sign ? -absZ : absZ;
92
93}
94
deps/SoftFloat-3e/source/f32_to_ui32.c deleted-84
...@@ -1,84 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast32_t f32_to_ui32( float32_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast32_t sig;
51 uint_fast64_t sig64;
52 int_fast16_t shiftDist;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 sign = signF32UI( uiA );
59 exp = expF32UI( uiA );
60 sig = fracF32UI( uiA );
61 /*------------------------------------------------------------------------
62 *------------------------------------------------------------------------*/
63#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
64 if ( (exp == 0xFF) && sig ) {
65#if (ui32_fromNaN == ui32_fromPosOverflow)
66 sign = 0;
67#elif (ui32_fromNaN == ui32_fromNegOverflow)
68 sign = 1;
69#else
70 softfloat_raiseFlags( softfloat_flag_invalid );
71 return ui32_fromNaN;
72#endif
73 }
74#endif
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 if ( exp ) sig |= 0x00800000;
78 sig64 = (uint_fast64_t) sig<<32;
79 shiftDist = 0xAA - exp;
80 if ( 0 < shiftDist ) sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
81 return softfloat_roundToUI32( sign, sig64, roundingMode, exact );
82
83}
84
deps/SoftFloat-3e/source/f32_to_ui32_r_minMag.c deleted-88
...@@ -1,88 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast32_t f32_to_ui32_r_minMag( float32_t a, bool exact )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 int_fast16_t exp;
49 uint_fast32_t sig;
50 int_fast16_t shiftDist;
51 bool sign;
52 uint_fast32_t z;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 exp = expF32UI( uiA );
59 sig = fracF32UI( uiA );
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = 0x9E - exp;
63 if ( 32 <= shiftDist ) {
64 if ( exact && (exp | sig) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signF32UI( uiA );
72 if ( sign || (shiftDist < 0) ) {
73 softfloat_raiseFlags( softfloat_flag_invalid );
74 return
75 (exp == 0xFF) && sig ? ui32_fromNaN
76 : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
77 }
78 /*------------------------------------------------------------------------
79 *------------------------------------------------------------------------*/
80 sig = (sig | 0x00800000)<<8;
81 z = sig>>shiftDist;
82 if ( exact && (z<<shiftDist != sig) ) {
83 softfloat_exceptionFlags |= softfloat_flag_inexact;
84 }
85 return z;
86
87}
88
deps/SoftFloat-3e/source/f32_to_ui64.c deleted-96
...@@ -1,96 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast64_t f32_to_ui64( float32_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast32_t sig;
51 int_fast16_t shiftDist;
52#ifdef SOFTFLOAT_FAST_INT64
53 uint_fast64_t sig64, extra;
54 struct uint64_extra sig64Extra;
55#else
56 uint32_t extSig[3];
57#endif
58
59 /*------------------------------------------------------------------------
60 *------------------------------------------------------------------------*/
61 uA.f = a;
62 uiA = uA.ui;
63 sign = signF32UI( uiA );
64 exp = expF32UI( uiA );
65 sig = fracF32UI( uiA );
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 shiftDist = 0xBE - exp;
69 if ( shiftDist < 0 ) {
70 softfloat_raiseFlags( softfloat_flag_invalid );
71 return
72 (exp == 0xFF) && sig ? ui64_fromNaN
73 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
74 }
75 /*------------------------------------------------------------------------
76 *------------------------------------------------------------------------*/
77 if ( exp ) sig |= 0x00800000;
78#ifdef SOFTFLOAT_FAST_INT64
79 sig64 = (uint_fast64_t) sig<<40;
80 extra = 0;
81 if ( shiftDist ) {
82 sig64Extra = softfloat_shiftRightJam64Extra( sig64, 0, shiftDist );
83 sig64 = sig64Extra.v;
84 extra = sig64Extra.extra;
85 }
86 return softfloat_roundToUI64( sign, sig64, extra, roundingMode, exact );
87#else
88 extSig[indexWord( 3, 2 )] = sig<<8;
89 extSig[indexWord( 3, 1 )] = 0;
90 extSig[indexWord( 3, 0 )] = 0;
91 if ( shiftDist ) softfloat_shiftRightJam96M( extSig, shiftDist, extSig );
92 return softfloat_roundMToUI64( sign, extSig, roundingMode, exact );
93#endif
94
95}
96
deps/SoftFloat-3e/source/f32_to_ui64_r_minMag.c deleted-90
...@@ -1,90 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast64_t f32_to_ui64_r_minMag( float32_t a, bool exact )
45{
46 union ui32_f32 uA;
47 uint_fast32_t uiA;
48 int_fast16_t exp;
49 uint_fast32_t sig;
50 int_fast16_t shiftDist;
51 bool sign;
52 uint_fast64_t sig64, z;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 exp = expF32UI( uiA );
59 sig = fracF32UI( uiA );
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = 0xBE - exp;
63 if ( 64 <= shiftDist ) {
64 if ( exact && (exp | sig) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signF32UI( uiA );
72 if ( sign || (shiftDist < 0) ) {
73 softfloat_raiseFlags( softfloat_flag_invalid );
74 return
75 (exp == 0xFF) && sig ? ui64_fromNaN
76 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
77 }
78 /*------------------------------------------------------------------------
79 *------------------------------------------------------------------------*/
80 sig |= 0x00800000;
81 sig64 = (uint_fast64_t) sig<<40;
82 z = sig64>>shiftDist;
83 shiftDist = 40 - shiftDist;
84 if ( exact && (shiftDist < 0) && (uint32_t) (sig<<(shiftDist & 31)) ) {
85 softfloat_exceptionFlags |= softfloat_flag_inexact;
86 }
87 return z;
88
89}
90
deps/SoftFloat-3e/source/f64_add.c deleted-74
...@@ -1,74 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float64_t f64_add( float64_t a, float64_t b )
44{
45 union ui64_f64 uA;
46 uint_fast64_t uiA;
47 bool signA;
48 union ui64_f64 uB;
49 uint_fast64_t uiB;
50 bool signB;
51#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
52 float64_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, bool );
53#endif
54
55 uA.f = a;
56 uiA = uA.ui;
57 signA = signF64UI( uiA );
58 uB.f = b;
59 uiB = uB.ui;
60 signB = signF64UI( uiB );
61#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
62 if ( signA == signB ) {
63 return softfloat_addMagsF64( uiA, uiB, signA );
64 } else {
65 return softfloat_subMagsF64( uiA, uiB, signA );
66 }
67#else
68 magsFuncPtr =
69 (signA == signB) ? softfloat_addMagsF64 : softfloat_subMagsF64;
70 return (*magsFuncPtr)( uiA, uiB, signA );
71#endif
72
73}
74
deps/SoftFloat-3e/source/f64_div.c deleted-172
...@@ -1,172 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float64_t f64_div( float64_t a, float64_t b )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool signA;
49 int_fast16_t expA;
50 uint_fast64_t sigA;
51 union ui64_f64 uB;
52 uint_fast64_t uiB;
53 bool signB;
54 int_fast16_t expB;
55 uint_fast64_t sigB;
56 bool signZ;
57 struct exp16_sig64 normExpSig;
58 int_fast16_t expZ;
59 uint32_t recip32, sig32Z, doubleTerm;
60 uint_fast64_t rem;
61 uint32_t q;
62 uint_fast64_t sigZ;
63 uint_fast64_t uiZ;
64 union ui64_f64 uZ;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 uA.f = a;
69 uiA = uA.ui;
70 signA = signF64UI( uiA );
71 expA = expF64UI( uiA );
72 sigA = fracF64UI( uiA );
73 uB.f = b;
74 uiB = uB.ui;
75 signB = signF64UI( uiB );
76 expB = expF64UI( uiB );
77 sigB = fracF64UI( uiB );
78 signZ = signA ^ signB;
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 if ( expA == 0x7FF ) {
82 if ( sigA ) goto propagateNaN;
83 if ( expB == 0x7FF ) {
84 if ( sigB ) goto propagateNaN;
85 goto invalid;
86 }
87 goto infinity;
88 }
89 if ( expB == 0x7FF ) {
90 if ( sigB ) goto propagateNaN;
91 goto zero;
92 }
93 /*------------------------------------------------------------------------
94 *------------------------------------------------------------------------*/
95 if ( ! expB ) {
96 if ( ! sigB ) {
97 if ( ! (expA | sigA) ) goto invalid;
98 softfloat_raiseFlags( softfloat_flag_infinite );
99 goto infinity;
100 }
101 normExpSig = softfloat_normSubnormalF64Sig( sigB );
102 expB = normExpSig.exp;
103 sigB = normExpSig.sig;
104 }
105 if ( ! expA ) {
106 if ( ! sigA ) goto zero;
107 normExpSig = softfloat_normSubnormalF64Sig( sigA );
108 expA = normExpSig.exp;
109 sigA = normExpSig.sig;
110 }
111 /*------------------------------------------------------------------------
112 *------------------------------------------------------------------------*/
113 expZ = expA - expB + 0x3FE;
114 sigA |= UINT64_C( 0x0010000000000000 );
115 sigB |= UINT64_C( 0x0010000000000000 );
116 if ( sigA < sigB ) {
117 --expZ;
118 sigA <<= 11;
119 } else {
120 sigA <<= 10;
121 }
122 sigB <<= 11;
123 recip32 = softfloat_approxRecip32_1( sigB>>32 ) - 2;
124 sig32Z = ((uint32_t) (sigA>>32) * (uint_fast64_t) recip32)>>32;
125 doubleTerm = sig32Z<<1;
126 rem =
127 ((sigA - (uint_fast64_t) doubleTerm * (uint32_t) (sigB>>32))<<28)
128 - (uint_fast64_t) doubleTerm * ((uint32_t) sigB>>4);
129 q = (((uint32_t) (rem>>32) * (uint_fast64_t) recip32)>>32) + 4;
130 sigZ = ((uint_fast64_t) sig32Z<<32) + ((uint_fast64_t) q<<4);
131 /*------------------------------------------------------------------------
132 *------------------------------------------------------------------------*/
133 if ( (sigZ & 0x1FF) < 4<<4 ) {
134 q &= ~7;
135 sigZ &= ~(uint_fast64_t) 0x7F;
136 doubleTerm = q<<1;
137 rem =
138 ((rem - (uint_fast64_t) doubleTerm * (uint32_t) (sigB>>32))<<28)
139 - (uint_fast64_t) doubleTerm * ((uint32_t) sigB>>4);
140 if ( rem & UINT64_C( 0x8000000000000000 ) ) {
141 sigZ -= 1<<7;
142 } else {
143 if ( rem ) sigZ |= 1;
144 }
145 }
146 return softfloat_roundPackToF64( signZ, expZ, sigZ );
147 /*------------------------------------------------------------------------
148 *------------------------------------------------------------------------*/
149 propagateNaN:
150 uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
151 goto uiZ;
152 /*------------------------------------------------------------------------
153 *------------------------------------------------------------------------*/
154 invalid:
155 softfloat_raiseFlags( softfloat_flag_invalid );
156 uiZ = defaultNaNF64UI;
157 goto uiZ;
158 /*------------------------------------------------------------------------
159 *------------------------------------------------------------------------*/
160 infinity:
161 uiZ = packToF64UI( signZ, 0x7FF, 0 );
162 goto uiZ;
163 /*------------------------------------------------------------------------
164 *------------------------------------------------------------------------*/
165 zero:
166 uiZ = packToF64UI( signZ, 0, 0 );
167 uiZ:
168 uZ.ui = uiZ;
169 return uZ.f;
170
171}
172
deps/SoftFloat-3e/source/f64_eq.c deleted-66
...@@ -1,66 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool f64_eq( float64_t a, float64_t b )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 union ui64_f64 uB;
49 uint_fast64_t uiB;
50
51 uA.f = a;
52 uiA = uA.ui;
53 uB.f = b;
54 uiB = uB.ui;
55 if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) {
56 if (
57 softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB )
58 ) {
59 softfloat_raiseFlags( softfloat_flag_invalid );
60 }
61 return false;
62 }
63 return (uiA == uiB) || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ));
64
65}
66
deps/SoftFloat-3e/source/f64_eq_signaling.c deleted-61
...@@ -1,61 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43bool f64_eq_signaling( float64_t a, float64_t b )
44{
45 union ui64_f64 uA;
46 uint_fast64_t uiA;
47 union ui64_f64 uB;
48 uint_fast64_t uiB;
49
50 uA.f = a;
51 uiA = uA.ui;
52 uB.f = b;
53 uiB = uB.ui;
54 if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) {
55 softfloat_raiseFlags( softfloat_flag_invalid );
56 return false;
57 }
58 return (uiA == uiB) || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ));
59
60}
61
deps/SoftFloat-3e/source/f64_isSignalingNaN.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include "platform.h"
39#include "internals.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43bool f64_isSignalingNaN( float64_t a )
44{
45 union ui64_f64 uA;
46
47 uA.f = a;
48 return softfloat_isSigNaNF64UI( uA.ui );
49
50}
51
deps/SoftFloat-3e/source/f64_le.c deleted-67
...@@ -1,67 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43bool f64_le( float64_t a, float64_t b )
44{
45 union ui64_f64 uA;
46 uint_fast64_t uiA;
47 union ui64_f64 uB;
48 uint_fast64_t uiB;
49 bool signA, signB;
50
51 uA.f = a;
52 uiA = uA.ui;
53 uB.f = b;
54 uiB = uB.ui;
55 if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) {
56 softfloat_raiseFlags( softfloat_flag_invalid );
57 return false;
58 }
59 signA = signF64UI( uiA );
60 signB = signF64UI( uiB );
61 return
62 (signA != signB)
63 ? signA || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
64 : (uiA == uiB) || (signA ^ (uiA < uiB));
65
66}
67
deps/SoftFloat-3e/source/f64_le_quiet.c deleted-72
...@@ -1,72 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool f64_le_quiet( float64_t a, float64_t b )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 union ui64_f64 uB;
49 uint_fast64_t uiB;
50 bool signA, signB;
51
52 uA.f = a;
53 uiA = uA.ui;
54 uB.f = b;
55 uiB = uB.ui;
56 if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) {
57 if (
58 softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB )
59 ) {
60 softfloat_raiseFlags( softfloat_flag_invalid );
61 }
62 return false;
63 }
64 signA = signF64UI( uiA );
65 signB = signF64UI( uiB );
66 return
67 (signA != signB)
68 ? signA || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
69 : (uiA == uiB) || (signA ^ (uiA < uiB));
70
71}
72
deps/SoftFloat-3e/source/f64_lt.c deleted-67
...@@ -1,67 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43bool f64_lt( float64_t a, float64_t b )
44{
45 union ui64_f64 uA;
46 uint_fast64_t uiA;
47 union ui64_f64 uB;
48 uint_fast64_t uiB;
49 bool signA, signB;
50
51 uA.f = a;
52 uiA = uA.ui;
53 uB.f = b;
54 uiB = uB.ui;
55 if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) {
56 softfloat_raiseFlags( softfloat_flag_invalid );
57 return false;
58 }
59 signA = signF64UI( uiA );
60 signB = signF64UI( uiB );
61 return
62 (signA != signB)
63 ? signA && ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
64 : (uiA != uiB) && (signA ^ (uiA < uiB));
65
66}
67
deps/SoftFloat-3e/source/f64_lt_quiet.c deleted-72
...@@ -1,72 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44bool f64_lt_quiet( float64_t a, float64_t b )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 union ui64_f64 uB;
49 uint_fast64_t uiB;
50 bool signA, signB;
51
52 uA.f = a;
53 uiA = uA.ui;
54 uB.f = b;
55 uiB = uB.ui;
56 if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) {
57 if (
58 softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB )
59 ) {
60 softfloat_raiseFlags( softfloat_flag_invalid );
61 }
62 return false;
63 }
64 signA = signF64UI( uiA );
65 signB = signF64UI( uiB );
66 return
67 (signA != signB)
68 ? signA && ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
69 : (uiA != uiB) && (signA ^ (uiA < uiB));
70
71}
72
deps/SoftFloat-3e/source/f64_mul.c deleted-150
...@@ -1,150 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float64_t f64_mul( float64_t a, float64_t b )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool signA;
49 int_fast16_t expA;
50 uint_fast64_t sigA;
51 union ui64_f64 uB;
52 uint_fast64_t uiB;
53 bool signB;
54 int_fast16_t expB;
55 uint_fast64_t sigB;
56 bool signZ;
57 uint_fast64_t magBits;
58 struct exp16_sig64 normExpSig;
59 int_fast16_t expZ;
60#ifdef SOFTFLOAT_FAST_INT64
61 struct uint128 sig128Z;
62#else
63 uint32_t sig128Z[4];
64#endif
65 uint_fast64_t sigZ, uiZ;
66 union ui64_f64 uZ;
67
68 /*------------------------------------------------------------------------
69 *------------------------------------------------------------------------*/
70 uA.f = a;
71 uiA = uA.ui;
72 signA = signF64UI( uiA );
73 expA = expF64UI( uiA );
74 sigA = fracF64UI( uiA );
75 uB.f = b;
76 uiB = uB.ui;
77 signB = signF64UI( uiB );
78 expB = expF64UI( uiB );
79 sigB = fracF64UI( uiB );
80 signZ = signA ^ signB;
81 /*------------------------------------------------------------------------
82 *------------------------------------------------------------------------*/
83 if ( expA == 0x7FF ) {
84 if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN;
85 magBits = expB | sigB;
86 goto infArg;
87 }
88 if ( expB == 0x7FF ) {
89 if ( sigB ) goto propagateNaN;
90 magBits = expA | sigA;
91 goto infArg;
92 }
93 /*------------------------------------------------------------------------
94 *------------------------------------------------------------------------*/
95 if ( ! expA ) {
96 if ( ! sigA ) goto zero;
97 normExpSig = softfloat_normSubnormalF64Sig( sigA );
98 expA = normExpSig.exp;
99 sigA = normExpSig.sig;
100 }
101 if ( ! expB ) {
102 if ( ! sigB ) goto zero;
103 normExpSig = softfloat_normSubnormalF64Sig( sigB );
104 expB = normExpSig.exp;
105 sigB = normExpSig.sig;
106 }
107 /*------------------------------------------------------------------------
108 *------------------------------------------------------------------------*/
109 expZ = expA + expB - 0x3FF;
110 sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10;
111 sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<11;
112#ifdef SOFTFLOAT_FAST_INT64
113 sig128Z = softfloat_mul64To128( sigA, sigB );
114 sigZ = sig128Z.v64 | (sig128Z.v0 != 0);
115#else
116 softfloat_mul64To128M( sigA, sigB, sig128Z );
117 sigZ =
118 (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )];
119 if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) sigZ |= 1;
120#endif
121 if ( sigZ < UINT64_C( 0x4000000000000000 ) ) {
122 --expZ;
123 sigZ <<= 1;
124 }
125 return softfloat_roundPackToF64( signZ, expZ, sigZ );
126 /*------------------------------------------------------------------------
127 *------------------------------------------------------------------------*/
128 propagateNaN:
129 uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
130 goto uiZ;
131 /*------------------------------------------------------------------------
132 *------------------------------------------------------------------------*/
133 infArg:
134 if ( ! magBits ) {
135 softfloat_raiseFlags( softfloat_flag_invalid );
136 uiZ = defaultNaNF64UI;
137 } else {
138 uiZ = packToF64UI( signZ, 0x7FF, 0 );
139 }
140 goto uiZ;
141 /*------------------------------------------------------------------------
142 *------------------------------------------------------------------------*/
143 zero:
144 uiZ = packToF64UI( signZ, 0, 0 );
145 uiZ:
146 uZ.ui = uiZ;
147 return uZ.f;
148
149}
150
deps/SoftFloat-3e/source/f64_mulAdd.c deleted-60
...@@ -1,60 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float64_t f64_mulAdd( float64_t a, float64_t b, float64_t c )
43{
44 union ui64_f64 uA;
45 uint_fast64_t uiA;
46 union ui64_f64 uB;
47 uint_fast64_t uiB;
48 union ui64_f64 uC;
49 uint_fast64_t uiC;
50
51 uA.f = a;
52 uiA = uA.ui;
53 uB.f = b;
54 uiB = uB.ui;
55 uC.f = c;
56 uiC = uC.ui;
57 return softfloat_mulAddF64( uiA, uiB, uiC, 0 );
58
59}
60
deps/SoftFloat-3e/source/f64_rem.c deleted-189
...@@ -1,189 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float64_t f64_rem( float64_t a, float64_t b )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool signA;
49 int_fast16_t expA;
50 uint_fast64_t sigA;
51 union ui64_f64 uB;
52 uint_fast64_t uiB;
53 int_fast16_t expB;
54 uint_fast64_t sigB;
55 struct exp16_sig64 normExpSig;
56 uint64_t rem;
57 int_fast16_t expDiff;
58 uint32_t q, recip32;
59 uint_fast64_t q64;
60 uint64_t altRem, meanRem;
61 bool signRem;
62 uint_fast64_t uiZ;
63 union ui64_f64 uZ;
64
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 uA.f = a;
68 uiA = uA.ui;
69 signA = signF64UI( uiA );
70 expA = expF64UI( uiA );
71 sigA = fracF64UI( uiA );
72 uB.f = b;
73 uiB = uB.ui;
74 expB = expF64UI( uiB );
75 sigB = fracF64UI( uiB );
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 if ( expA == 0x7FF ) {
79 if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN;
80 goto invalid;
81 }
82 if ( expB == 0x7FF ) {
83 if ( sigB ) goto propagateNaN;
84 return a;
85 }
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 if ( expA < expB - 1 ) return a;
89 /*------------------------------------------------------------------------
90 *------------------------------------------------------------------------*/
91 if ( ! expB ) {
92 if ( ! sigB ) goto invalid;
93 normExpSig = softfloat_normSubnormalF64Sig( sigB );
94 expB = normExpSig.exp;
95 sigB = normExpSig.sig;
96 }
97 if ( ! expA ) {
98 if ( ! sigA ) return a;
99 normExpSig = softfloat_normSubnormalF64Sig( sigA );
100 expA = normExpSig.exp;
101 sigA = normExpSig.sig;
102 }
103 /*------------------------------------------------------------------------
104 *------------------------------------------------------------------------*/
105 rem = sigA | UINT64_C( 0x0010000000000000 );
106 sigB |= UINT64_C( 0x0010000000000000 );
107 expDiff = expA - expB;
108 if ( expDiff < 1 ) {
109 if ( expDiff < -1 ) return a;
110 sigB <<= 9;
111 if ( expDiff ) {
112 rem <<= 8;
113 q = 0;
114 } else {
115 rem <<= 9;
116 q = (sigB <= rem);
117 if ( q ) rem -= sigB;
118 }
119 } else {
120 recip32 = softfloat_approxRecip32_1( sigB>>21 );
121 /*--------------------------------------------------------------------
122 | Changing the shift of `rem' here requires also changing the initial
123 | subtraction from `expDiff'.
124 *--------------------------------------------------------------------*/
125 rem <<= 9;
126 expDiff -= 30;
127 /*--------------------------------------------------------------------
128 | The scale of `sigB' affects how many bits are obtained during each
129 | cycle of the loop. Currently this is 29 bits per loop iteration,
130 | the maximum possible.
131 *--------------------------------------------------------------------*/
132 sigB <<= 9;
133 for (;;) {
134 q64 = (uint32_t) (rem>>32) * (uint_fast64_t) recip32;
135 if ( expDiff < 0 ) break;
136 q = (q64 + 0x80000000)>>32;
137#ifdef SOFTFLOAT_FAST_INT64
138 rem <<= 29;
139#else
140 rem = (uint_fast64_t) (uint32_t) (rem>>3)<<32;
141#endif
142 rem -= q * (uint64_t) sigB;
143 if ( rem & UINT64_C( 0x8000000000000000 ) ) rem += sigB;
144 expDiff -= 29;
145 }
146 /*--------------------------------------------------------------------
147 | (`expDiff' cannot be less than -29 here.)
148 *--------------------------------------------------------------------*/
149 q = (uint32_t) (q64>>32)>>(~expDiff & 31);
150 rem = (rem<<(expDiff + 30)) - q * (uint64_t) sigB;
151 if ( rem & UINT64_C( 0x8000000000000000 ) ) {
152 altRem = rem + sigB;
153 goto selectRem;
154 }
155 }
156 /*------------------------------------------------------------------------
157 *------------------------------------------------------------------------*/
158 do {
159 altRem = rem;
160 ++q;
161 rem -= sigB;
162 } while ( ! (rem & UINT64_C( 0x8000000000000000 )) );
163 selectRem:
164 meanRem = rem + altRem;
165 if (
166 (meanRem & UINT64_C( 0x8000000000000000 )) || (! meanRem && (q & 1))
167 ) {
168 rem = altRem;
169 }
170 signRem = signA;
171 if ( rem & UINT64_C( 0x8000000000000000 ) ) {
172 signRem = ! signRem;
173 rem = -rem;
174 }
175 return softfloat_normRoundPackToF64( signRem, expB, rem );
176 /*------------------------------------------------------------------------
177 *------------------------------------------------------------------------*/
178 propagateNaN:
179 uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
180 goto uiZ;
181 invalid:
182 softfloat_raiseFlags( softfloat_flag_invalid );
183 uiZ = defaultNaNF64UI;
184 uiZ:
185 uZ.ui = uiZ;
186 return uZ.f;
187
188}
189
deps/SoftFloat-3e/source/f64_roundToInt.c deleted-120
...@@ -1,120 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float64_t f64_roundToInt( float64_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 int_fast16_t exp;
49 uint_fast64_t uiZ, lastBitMask, roundBitsMask;
50 union ui64_f64 uZ;
51
52 /*------------------------------------------------------------------------
53 *------------------------------------------------------------------------*/
54 uA.f = a;
55 uiA = uA.ui;
56 exp = expF64UI( uiA );
57 /*------------------------------------------------------------------------
58 *------------------------------------------------------------------------*/
59 if ( exp <= 0x3FE ) {
60 if ( !(uiA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) return a;
61 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
62 uiZ = uiA & packToF64UI( 1, 0, 0 );
63 switch ( roundingMode ) {
64 case softfloat_round_near_even:
65 if ( !fracF64UI( uiA ) ) break;
66 case softfloat_round_near_maxMag:
67 if ( exp == 0x3FE ) uiZ |= packToF64UI( 0, 0x3FF, 0 );
68 break;
69 case softfloat_round_min:
70 if ( uiZ ) uiZ = packToF64UI( 1, 0x3FF, 0 );
71 break;
72 case softfloat_round_max:
73 if ( !uiZ ) uiZ = packToF64UI( 0, 0x3FF, 0 );
74 break;
75#ifdef SOFTFLOAT_ROUND_ODD
76 case softfloat_round_odd:
77 uiZ |= packToF64UI( 0, 0x3FF, 0 );
78 break;
79#endif
80 }
81 goto uiZ;
82 }
83 /*------------------------------------------------------------------------
84 *------------------------------------------------------------------------*/
85 if ( 0x433 <= exp ) {
86 if ( (exp == 0x7FF) && fracF64UI( uiA ) ) {
87 uiZ = softfloat_propagateNaNF64UI( uiA, 0 );
88 goto uiZ;
89 }
90 return a;
91 }
92 /*------------------------------------------------------------------------
93 *------------------------------------------------------------------------*/
94 uiZ = uiA;
95 lastBitMask = (uint_fast64_t) 1<<(0x433 - exp);
96 roundBitsMask = lastBitMask - 1;
97 if ( roundingMode == softfloat_round_near_maxMag ) {
98 uiZ += lastBitMask>>1;
99 } else if ( roundingMode == softfloat_round_near_even ) {
100 uiZ += lastBitMask>>1;
101 if ( !(uiZ & roundBitsMask) ) uiZ &= ~lastBitMask;
102 } else if (
103 roundingMode
104 == (signF64UI( uiZ ) ? softfloat_round_min : softfloat_round_max)
105 ) {
106 uiZ += roundBitsMask;
107 }
108 uiZ &= ~roundBitsMask;
109 if ( uiZ != uiA ) {
110#ifdef SOFTFLOAT_ROUND_ODD
111 if ( roundingMode == softfloat_round_odd ) uiZ |= lastBitMask;
112#endif
113 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
114 }
115 uiZ:
116 uZ.ui = uiZ;
117 return uZ.f;
118
119}
120
deps/SoftFloat-3e/source/f64_sqrt.c deleted-133
...@@ -1,133 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float64_t f64_sqrt( float64_t a )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool signA;
49 int_fast16_t expA;
50 uint_fast64_t sigA, uiZ;
51 struct exp16_sig64 normExpSig;
52 int_fast16_t expZ;
53 uint32_t sig32A, recipSqrt32, sig32Z;
54 uint_fast64_t rem;
55 uint32_t q;
56 uint_fast64_t sigZ, shiftedSigZ;
57 union ui64_f64 uZ;
58
59 /*------------------------------------------------------------------------
60 *------------------------------------------------------------------------*/
61 uA.f = a;
62 uiA = uA.ui;
63 signA = signF64UI( uiA );
64 expA = expF64UI( uiA );
65 sigA = fracF64UI( uiA );
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 if ( expA == 0x7FF ) {
69 if ( sigA ) {
70 uiZ = softfloat_propagateNaNF64UI( uiA, 0 );
71 goto uiZ;
72 }
73 if ( ! signA ) return a;
74 goto invalid;
75 }
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 if ( signA ) {
79 if ( ! (expA | sigA) ) return a;
80 goto invalid;
81 }
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( ! expA ) {
85 if ( ! sigA ) return a;
86 normExpSig = softfloat_normSubnormalF64Sig( sigA );
87 expA = normExpSig.exp;
88 sigA = normExpSig.sig;
89 }
90 /*------------------------------------------------------------------------
91 | (`sig32Z' is guaranteed to be a lower bound on the square root of
92 | `sig32A', which makes `sig32Z' also a lower bound on the square root of
93 | `sigA'.)
94 *------------------------------------------------------------------------*/
95 expZ = ((expA - 0x3FF)>>1) + 0x3FE;
96 expA &= 1;
97 sigA |= UINT64_C( 0x0010000000000000 );
98 sig32A = sigA>>21;
99 recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A );
100 sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32;
101 if ( expA ) {
102 sigA <<= 8;
103 sig32Z >>= 1;
104 } else {
105 sigA <<= 9;
106 }
107 rem = sigA - (uint_fast64_t) sig32Z * sig32Z;
108 q = ((uint32_t) (rem>>2) * (uint_fast64_t) recipSqrt32)>>32;
109 sigZ = ((uint_fast64_t) sig32Z<<32 | 1<<5) + ((uint_fast64_t) q<<3);
110 /*------------------------------------------------------------------------
111 *------------------------------------------------------------------------*/
112 if ( (sigZ & 0x1FF) < 0x22 ) {
113 sigZ &= ~(uint_fast64_t) 0x3F;
114 shiftedSigZ = sigZ>>6;
115 rem = (sigA<<52) - shiftedSigZ * shiftedSigZ;
116 if ( rem & UINT64_C( 0x8000000000000000 ) ) {
117 --sigZ;
118 } else {
119 if ( rem ) sigZ |= 1;
120 }
121 }
122 return softfloat_roundPackToF64( 0, expZ, sigZ );
123 /*------------------------------------------------------------------------
124 *------------------------------------------------------------------------*/
125 invalid:
126 softfloat_raiseFlags( softfloat_flag_invalid );
127 uiZ = defaultNaNF64UI;
128 uiZ:
129 uZ.ui = uiZ;
130 return uZ.f;
131
132}
133
deps/SoftFloat-3e/source/f64_sub.c deleted-74
...@@ -1,74 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float64_t f64_sub( float64_t a, float64_t b )
44{
45 union ui64_f64 uA;
46 uint_fast64_t uiA;
47 bool signA;
48 union ui64_f64 uB;
49 uint_fast64_t uiB;
50 bool signB;
51#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
52 float64_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, bool );
53#endif
54
55 uA.f = a;
56 uiA = uA.ui;
57 signA = signF64UI( uiA );
58 uB.f = b;
59 uiB = uB.ui;
60 signB = signF64UI( uiB );
61#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
62 if ( signA == signB ) {
63 return softfloat_subMagsF64( uiA, uiB, signA );
64 } else {
65 return softfloat_addMagsF64( uiA, uiB, signA );
66 }
67#else
68 magsFuncPtr =
69 (signA == signB) ? softfloat_subMagsF64 : softfloat_addMagsF64;
70 return (*magsFuncPtr)( uiA, uiB, signA );
71#endif
72
73}
74
deps/SoftFloat-3e/source/f64_to_extF80.c deleted-101
...@@ -1,101 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44extFloat80_t f64_to_extF80( float64_t a )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast64_t frac;
51 struct commonNaN commonNaN;
52 struct uint128 uiZ;
53 uint_fast16_t uiZ64;
54 uint_fast64_t uiZ0;
55 struct exp16_sig64 normExpSig;
56 union { struct extFloat80M s; extFloat80_t f; } uZ;
57
58 /*------------------------------------------------------------------------
59 *------------------------------------------------------------------------*/
60 uA.f = a;
61 uiA = uA.ui;
62 sign = signF64UI( uiA );
63 exp = expF64UI( uiA );
64 frac = fracF64UI( uiA );
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 if ( exp == 0x7FF ) {
68 if ( frac ) {
69 softfloat_f64UIToCommonNaN( uiA, &commonNaN );
70 uiZ = softfloat_commonNaNToExtF80UI( &commonNaN );
71 uiZ64 = uiZ.v64;
72 uiZ0 = uiZ.v0;
73 } else {
74 uiZ64 = packToExtF80UI64( sign, 0x7FFF );
75 uiZ0 = UINT64_C( 0x8000000000000000 );
76 }
77 goto uiZ;
78 }
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 if ( ! exp ) {
82 if ( ! frac ) {
83 uiZ64 = packToExtF80UI64( sign, 0 );
84 uiZ0 = 0;
85 goto uiZ;
86 }
87 normExpSig = softfloat_normSubnormalF64Sig( frac );
88 exp = normExpSig.exp;
89 frac = normExpSig.sig;
90 }
91 /*------------------------------------------------------------------------
92 *------------------------------------------------------------------------*/
93 uiZ64 = packToExtF80UI64( sign, exp + 0x3C00 );
94 uiZ0 = (frac | UINT64_C( 0x0010000000000000 ))<<11;
95 uiZ:
96 uZ.s.signExp = uiZ64;
97 uZ.s.signif = uiZ0;
98 return uZ.f;
99
100}
101
deps/SoftFloat-3e/source/f64_to_extF80M.c deleted-111
...@@ -1,111 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void f64_to_extF80M( float64_t a, extFloat80_t *zPtr )
47{
48
49 *zPtr = f64_to_extF80( a );
50
51}
52
53#else
54
55void f64_to_extF80M( float64_t a, extFloat80_t *zPtr )
56{
57 struct extFloat80M *zSPtr;
58 union ui64_f64 uA;
59 uint64_t uiA;
60 bool sign;
61 int_fast16_t exp;
62 uint64_t frac;
63 struct commonNaN commonNaN;
64 uint_fast16_t uiZ64;
65 uint64_t uiZ0;
66 struct exp16_sig64 normExpSig;
67
68 /*------------------------------------------------------------------------
69 *------------------------------------------------------------------------*/
70 zSPtr = (struct extFloat80M *) zPtr;
71 uA.f = a;
72 uiA = uA.ui;
73 sign = signF64UI( uiA );
74 exp = expF64UI( uiA );
75 frac = fracF64UI( uiA );
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 if ( exp == 0x7FF ) {
79 if ( frac ) {
80 softfloat_f64UIToCommonNaN( uiA, &commonNaN );
81 softfloat_commonNaNToExtF80M( &commonNaN, zSPtr );
82 return;
83 }
84 uiZ64 = packToExtF80UI64( sign, 0x7FFF );
85 uiZ0 = UINT64_C( 0x8000000000000000 );
86 goto uiZ;
87 }
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 if ( ! exp ) {
91 if ( ! frac ) {
92 uiZ64 = packToExtF80UI64( sign, 0 );
93 uiZ0 = 0;
94 goto uiZ;
95 }
96 normExpSig = softfloat_normSubnormalF64Sig( frac );
97 exp = normExpSig.exp;
98 frac = normExpSig.sig;
99 }
100 /*------------------------------------------------------------------------
101 *------------------------------------------------------------------------*/
102 uiZ64 = packToExtF80UI64( sign, exp + 0x3C00 );
103 uiZ0 = UINT64_C( 0x8000000000000000 ) | frac<<11;
104 uiZ:
105 zSPtr->signExp = uiZ64;
106 zSPtr->signif = uiZ0;
107
108}
109
110#endif
111
deps/SoftFloat-3e/source/f64_to_f128.c deleted-98
...@@ -1,98 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float128_t f64_to_f128( float64_t a )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast64_t frac;
51 struct commonNaN commonNaN;
52 struct uint128 uiZ;
53 struct exp16_sig64 normExpSig;
54 struct uint128 frac128;
55 union ui128_f128 uZ;
56
57 /*------------------------------------------------------------------------
58 *------------------------------------------------------------------------*/
59 uA.f = a;
60 uiA = uA.ui;
61 sign = signF64UI( uiA );
62 exp = expF64UI( uiA );
63 frac = fracF64UI( uiA );
64 /*------------------------------------------------------------------------
65 *------------------------------------------------------------------------*/
66 if ( exp == 0x7FF ) {
67 if ( frac ) {
68 softfloat_f64UIToCommonNaN( uiA, &commonNaN );
69 uiZ = softfloat_commonNaNToF128UI( &commonNaN );
70 } else {
71 uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 );
72 uiZ.v0 = 0;
73 }
74 goto uiZ;
75 }
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 if ( ! exp ) {
79 if ( ! frac ) {
80 uiZ.v64 = packToF128UI64( sign, 0, 0 );
81 uiZ.v0 = 0;
82 goto uiZ;
83 }
84 normExpSig = softfloat_normSubnormalF64Sig( frac );
85 exp = normExpSig.exp - 1;
86 frac = normExpSig.sig;
87 }
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 frac128 = softfloat_shortShiftLeft128( 0, frac, 60 );
91 uiZ.v64 = packToF128UI64( sign, exp + 0x3C00, frac128.v64 );
92 uiZ.v0 = frac128.v0;
93 uiZ:
94 uZ.ui = uiZ;
95 return uZ.f;
96
97}
98
deps/SoftFloat-3e/source/f64_to_f128M.c deleted-117
...@@ -1,117 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46void f64_to_f128M( float64_t a, float128_t *zPtr )
47{
48
49 *zPtr = f64_to_f128( a );
50
51}
52
53#else
54
55void f64_to_f128M( float64_t a, float128_t *zPtr )
56{
57 uint32_t *zWPtr;
58 union ui64_f64 uA;
59 uint64_t uiA;
60 bool sign;
61 int_fast16_t exp;
62 uint64_t frac;
63 struct commonNaN commonNaN;
64 uint32_t uiZ96;
65 struct exp16_sig64 normExpSig;
66
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 zWPtr = (uint32_t *) zPtr;
70 /*------------------------------------------------------------------------
71 *------------------------------------------------------------------------*/
72 uA.f = a;
73 uiA = uA.ui;
74 sign = signF64UI( uiA );
75 exp = expF64UI( uiA );
76 frac = fracF64UI( uiA );
77 /*------------------------------------------------------------------------
78 *------------------------------------------------------------------------*/
79 zWPtr[indexWord( 4, 0 )] = 0;
80 if ( exp == 0x7FF ) {
81 if ( frac ) {
82 softfloat_f64UIToCommonNaN( uiA, &commonNaN );
83 softfloat_commonNaNToF128M( &commonNaN, zWPtr );
84 return;
85 }
86 uiZ96 = packToF128UI96( sign, 0x7FFF, 0 );
87 goto uiZ;
88 }
89 /*------------------------------------------------------------------------
90 *------------------------------------------------------------------------*/
91 if ( ! exp ) {
92 if ( ! frac ) {
93 uiZ96 = packToF128UI96( sign, 0, 0 );
94 goto uiZ;
95 }
96 normExpSig = softfloat_normSubnormalF64Sig( frac );
97 exp = normExpSig.exp - 1;
98 frac = normExpSig.sig;
99 }
100 /*------------------------------------------------------------------------
101 *------------------------------------------------------------------------*/
102 zWPtr[indexWord( 4, 1 )] = (uint32_t) frac<<28;
103 frac >>= 4;
104 zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, exp + 0x3C00, frac>>32 );
105 zWPtr[indexWord( 4, 2 )] = frac;
106 return;
107 /*------------------------------------------------------------------------
108 *------------------------------------------------------------------------*/
109 uiZ:
110 zWPtr[indexWord( 4, 3 )] = uiZ96;
111 zWPtr[indexWord( 4, 2 )] = 0;
112 zWPtr[indexWord( 4, 1 )] = 0;
113
114}
115
116#endif
117
deps/SoftFloat-3e/source/f64_to_f16.c deleted-88
...@@ -1,88 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float16_t f64_to_f16( float64_t a )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast64_t frac;
51 struct commonNaN commonNaN;
52 uint_fast16_t uiZ, frac16;
53 union ui16_f16 uZ;
54
55 /*------------------------------------------------------------------------
56 *------------------------------------------------------------------------*/
57 uA.f = a;
58 uiA = uA.ui;
59 sign = signF64UI( uiA );
60 exp = expF64UI( uiA );
61 frac = fracF64UI( uiA );
62 /*------------------------------------------------------------------------
63 *------------------------------------------------------------------------*/
64 if ( exp == 0x7FF ) {
65 if ( frac ) {
66 softfloat_f64UIToCommonNaN( uiA, &commonNaN );
67 uiZ = softfloat_commonNaNToF16UI( &commonNaN );
68 } else {
69 uiZ = packToF16UI( sign, 0x1F, 0 );
70 }
71 goto uiZ;
72 }
73 /*------------------------------------------------------------------------
74 *------------------------------------------------------------------------*/
75 frac16 = softfloat_shortShiftRightJam64( frac, 38 );
76 if ( ! (exp | frac16) ) {
77 uiZ = packToF16UI( sign, 0, 0 );
78 goto uiZ;
79 }
80 /*------------------------------------------------------------------------
81 *------------------------------------------------------------------------*/
82 return softfloat_roundPackToF16( sign, exp - 0x3F1, frac16 | 0x4000 );
83 uiZ:
84 uZ.ui = uiZ;
85 return uZ.f;
86
87}
88
deps/SoftFloat-3e/source/f64_to_f32.c deleted-88
...@@ -1,88 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float32_t f64_to_f32( float64_t a )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast64_t frac;
51 struct commonNaN commonNaN;
52 uint_fast32_t uiZ, frac32;
53 union ui32_f32 uZ;
54
55 /*------------------------------------------------------------------------
56 *------------------------------------------------------------------------*/
57 uA.f = a;
58 uiA = uA.ui;
59 sign = signF64UI( uiA );
60 exp = expF64UI( uiA );
61 frac = fracF64UI( uiA );
62 /*------------------------------------------------------------------------
63 *------------------------------------------------------------------------*/
64 if ( exp == 0x7FF ) {
65 if ( frac ) {
66 softfloat_f64UIToCommonNaN( uiA, &commonNaN );
67 uiZ = softfloat_commonNaNToF32UI( &commonNaN );
68 } else {
69 uiZ = packToF32UI( sign, 0xFF, 0 );
70 }
71 goto uiZ;
72 }
73 /*------------------------------------------------------------------------
74 *------------------------------------------------------------------------*/
75 frac32 = softfloat_shortShiftRightJam64( frac, 22 );
76 if ( ! (exp | frac32) ) {
77 uiZ = packToF32UI( sign, 0, 0 );
78 goto uiZ;
79 }
80 /*------------------------------------------------------------------------
81 *------------------------------------------------------------------------*/
82 return softfloat_roundPackToF32( sign, exp - 0x381, frac32 | 0x40000000 );
83 uiZ:
84 uZ.ui = uiZ;
85 return uZ.f;
86
87}
88
deps/SoftFloat-3e/source/f64_to_i32.c deleted-82
...@@ -1,82 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast32_t f64_to_i32( float64_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast64_t sig;
51 int_fast16_t shiftDist;
52
53 /*------------------------------------------------------------------------
54 *------------------------------------------------------------------------*/
55 uA.f = a;
56 uiA = uA.ui;
57 sign = signF64UI( uiA );
58 exp = expF64UI( uiA );
59 sig = fracF64UI( uiA );
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
63 if ( (exp == 0x7FF) && sig ) {
64#if (i32_fromNaN == i32_fromPosOverflow)
65 sign = 0;
66#elif (i32_fromNaN == i32_fromNegOverflow)
67 sign = 1;
68#else
69 softfloat_raiseFlags( softfloat_flag_invalid );
70 return i32_fromNaN;
71#endif
72 }
73#endif
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( exp ) sig |= UINT64_C( 0x0010000000000000 );
77 shiftDist = 0x427 - exp;
78 if ( 0 < shiftDist ) sig = softfloat_shiftRightJam64( sig, shiftDist );
79 return softfloat_roundToI32( sign, sig, roundingMode, exact );
80
81}
82
deps/SoftFloat-3e/source/f64_to_i32_r_minMag.c deleted-96
...@@ -1,96 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast32_t f64_to_i32_r_minMag( float64_t a, bool exact )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 int_fast16_t exp;
49 uint_fast64_t sig;
50 int_fast16_t shiftDist;
51 bool sign;
52 int_fast32_t absZ;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 exp = expF64UI( uiA );
59 sig = fracF64UI( uiA );
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = 0x433 - exp;
63 if ( 53 <= shiftDist ) {
64 if ( exact && (exp | sig) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signF64UI( uiA );
72 if ( shiftDist < 22 ) {
73 if (
74 sign && (exp == 0x41E) && (sig < UINT64_C( 0x0000000000200000 ))
75 ) {
76 if ( exact && sig ) {
77 softfloat_exceptionFlags |= softfloat_flag_inexact;
78 }
79 return -0x7FFFFFFF - 1;
80 }
81 softfloat_raiseFlags( softfloat_flag_invalid );
82 return
83 (exp == 0x7FF) && sig ? i32_fromNaN
84 : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
85 }
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 sig |= UINT64_C( 0x0010000000000000 );
89 absZ = sig>>shiftDist;
90 if ( exact && ((uint_fast64_t) (uint_fast32_t) absZ<<shiftDist != sig) ) {
91 softfloat_exceptionFlags |= softfloat_flag_inexact;
92 }
93 return sign ? -absZ : absZ;
94
95}
96
deps/SoftFloat-3e/source/f64_to_i64.c deleted-103
...@@ -1,103 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast64_t f64_to_i64( float64_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast64_t sig;
51 int_fast16_t shiftDist;
52#ifdef SOFTFLOAT_FAST_INT64
53 struct uint64_extra sigExtra;
54#else
55 uint32_t extSig[3];
56#endif
57
58 /*------------------------------------------------------------------------
59 *------------------------------------------------------------------------*/
60 uA.f = a;
61 uiA = uA.ui;
62 sign = signF64UI( uiA );
63 exp = expF64UI( uiA );
64 sig = fracF64UI( uiA );
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 if ( exp ) sig |= UINT64_C( 0x0010000000000000 );
68 shiftDist = 0x433 - exp;
69#ifdef SOFTFLOAT_FAST_INT64
70 if ( shiftDist <= 0 ) {
71 if ( shiftDist < -11 ) goto invalid;
72 sigExtra.v = sig<<-shiftDist;
73 sigExtra.extra = 0;
74 } else {
75 sigExtra = softfloat_shiftRightJam64Extra( sig, 0, shiftDist );
76 }
77 return
78 softfloat_roundToI64(
79 sign, sigExtra.v, sigExtra.extra, roundingMode, exact );
80#else
81 extSig[indexWord( 3, 0 )] = 0;
82 if ( shiftDist <= 0 ) {
83 if ( shiftDist < -11 ) goto invalid;
84 sig <<= -shiftDist;
85 extSig[indexWord( 3, 2 )] = sig>>32;
86 extSig[indexWord( 3, 1 )] = sig;
87 } else {
88 extSig[indexWord( 3, 2 )] = sig>>32;
89 extSig[indexWord( 3, 1 )] = sig;
90 softfloat_shiftRightJam96M( extSig, shiftDist, extSig );
91 }
92 return softfloat_roundMToI64( sign, extSig, roundingMode, exact );
93#endif
94 /*------------------------------------------------------------------------
95 *------------------------------------------------------------------------*/
96 invalid:
97 softfloat_raiseFlags( softfloat_flag_invalid );
98 return
99 (exp == 0x7FF) && fracF64UI( uiA ) ? i64_fromNaN
100 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
101
102}
103
deps/SoftFloat-3e/source/f64_to_i64_r_minMag.c deleted-100
...@@ -1,100 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast64_t f64_to_i64_r_minMag( float64_t a, bool exact )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast64_t sig;
51 int_fast16_t shiftDist;
52 int_fast64_t absZ;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 sign = signF64UI( uiA );
59 exp = expF64UI( uiA );
60 sig = fracF64UI( uiA );
61 /*------------------------------------------------------------------------
62 *------------------------------------------------------------------------*/
63 shiftDist = 0x433 - exp;
64 if ( shiftDist <= 0 ) {
65 /*--------------------------------------------------------------------
66 *--------------------------------------------------------------------*/
67 if ( shiftDist < -10 ) {
68 if ( uiA == packToF64UI( 1, 0x43E, 0 ) ) {
69 return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1;
70 }
71 softfloat_raiseFlags( softfloat_flag_invalid );
72 return
73 (exp == 0x7FF) && sig ? i64_fromNaN
74 : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
75 }
76 /*--------------------------------------------------------------------
77 *--------------------------------------------------------------------*/
78 sig |= UINT64_C( 0x0010000000000000 );
79 absZ = sig<<-shiftDist;
80 } else {
81 /*--------------------------------------------------------------------
82 *--------------------------------------------------------------------*/
83 if ( 53 <= shiftDist ) {
84 if ( exact && (exp | sig) ) {
85 softfloat_exceptionFlags |= softfloat_flag_inexact;
86 }
87 return 0;
88 }
89 /*--------------------------------------------------------------------
90 *--------------------------------------------------------------------*/
91 sig |= UINT64_C( 0x0010000000000000 );
92 absZ = sig>>shiftDist;
93 if ( exact && (absZ<<shiftDist != sig) ) {
94 softfloat_exceptionFlags |= softfloat_flag_inexact;
95 }
96 }
97 return sign ? -absZ : absZ;
98
99}
100
deps/SoftFloat-3e/source/f64_to_ui32.c deleted-82
...@@ -1,82 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast32_t f64_to_ui32( float64_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast64_t sig;
51 int_fast16_t shiftDist;
52
53 /*------------------------------------------------------------------------
54 *------------------------------------------------------------------------*/
55 uA.f = a;
56 uiA = uA.ui;
57 sign = signF64UI( uiA );
58 exp = expF64UI( uiA );
59 sig = fracF64UI( uiA );
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
63 if ( (exp == 0x7FF) && sig ) {
64#if (ui32_fromNaN == ui32_fromPosOverflow)
65 sign = 0;
66#elif (ui32_fromNaN == ui32_fromNegOverflow)
67 sign = 1;
68#else
69 softfloat_raiseFlags( softfloat_flag_invalid );
70 return ui32_fromNaN;
71#endif
72 }
73#endif
74 /*------------------------------------------------------------------------
75 *------------------------------------------------------------------------*/
76 if ( exp ) sig |= UINT64_C( 0x0010000000000000 );
77 shiftDist = 0x427 - exp;
78 if ( 0 < shiftDist ) sig = softfloat_shiftRightJam64( sig, shiftDist );
79 return softfloat_roundToUI32( sign, sig, roundingMode, exact );
80
81}
82
deps/SoftFloat-3e/source/f64_to_ui32_r_minMag.c deleted-88
...@@ -1,88 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast32_t f64_to_ui32_r_minMag( float64_t a, bool exact )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 int_fast16_t exp;
49 uint_fast64_t sig;
50 int_fast16_t shiftDist;
51 bool sign;
52 uint_fast32_t z;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 exp = expF64UI( uiA );
59 sig = fracF64UI( uiA );
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = 0x433 - exp;
63 if ( 53 <= shiftDist ) {
64 if ( exact && (exp | sig) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signF64UI( uiA );
72 if ( sign || (shiftDist < 21) ) {
73 softfloat_raiseFlags( softfloat_flag_invalid );
74 return
75 (exp == 0x7FF) && sig ? ui32_fromNaN
76 : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
77 }
78 /*------------------------------------------------------------------------
79 *------------------------------------------------------------------------*/
80 sig |= UINT64_C( 0x0010000000000000 );
81 z = sig>>shiftDist;
82 if ( exact && ((uint_fast64_t) z<<shiftDist != sig) ) {
83 softfloat_exceptionFlags |= softfloat_flag_inexact;
84 }
85 return z;
86
87}
88
deps/SoftFloat-3e/source/f64_to_ui64.c deleted-103
...@@ -1,103 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast64_t f64_to_ui64( float64_t a, uint_fast8_t roundingMode, bool exact )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool sign;
49 int_fast16_t exp;
50 uint_fast64_t sig;
51 int_fast16_t shiftDist;
52#ifdef SOFTFLOAT_FAST_INT64
53 struct uint64_extra sigExtra;
54#else
55 uint32_t extSig[3];
56#endif
57
58 /*------------------------------------------------------------------------
59 *------------------------------------------------------------------------*/
60 uA.f = a;
61 uiA = uA.ui;
62 sign = signF64UI( uiA );
63 exp = expF64UI( uiA );
64 sig = fracF64UI( uiA );
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 if ( exp ) sig |= UINT64_C( 0x0010000000000000 );
68 shiftDist = 0x433 - exp;
69#ifdef SOFTFLOAT_FAST_INT64
70 if ( shiftDist <= 0 ) {
71 if ( shiftDist < -11 ) goto invalid;
72 sigExtra.v = sig<<-shiftDist;
73 sigExtra.extra = 0;
74 } else {
75 sigExtra = softfloat_shiftRightJam64Extra( sig, 0, shiftDist );
76 }
77 return
78 softfloat_roundToUI64(
79 sign, sigExtra.v, sigExtra.extra, roundingMode, exact );
80#else
81 extSig[indexWord( 3, 0 )] = 0;
82 if ( shiftDist <= 0 ) {
83 if ( shiftDist < -11 ) goto invalid;
84 sig <<= -shiftDist;
85 extSig[indexWord( 3, 2 )] = sig>>32;
86 extSig[indexWord( 3, 1 )] = sig;
87 } else {
88 extSig[indexWord( 3, 2 )] = sig>>32;
89 extSig[indexWord( 3, 1 )] = sig;
90 softfloat_shiftRightJam96M( extSig, shiftDist, extSig );
91 }
92 return softfloat_roundMToUI64( sign, extSig, roundingMode, exact );
93#endif
94 /*------------------------------------------------------------------------
95 *------------------------------------------------------------------------*/
96 invalid:
97 softfloat_raiseFlags( softfloat_flag_invalid );
98 return
99 (exp == 0x7FF) && fracF64UI( uiA ) ? ui64_fromNaN
100 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
101
102}
103
deps/SoftFloat-3e/source/f64_to_ui64_r_minMag.c deleted-93
...@@ -1,93 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast64_t f64_to_ui64_r_minMag( float64_t a, bool exact )
45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 int_fast16_t exp;
49 uint_fast64_t sig;
50 int_fast16_t shiftDist;
51 bool sign;
52 uint_fast64_t z;
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 uA.f = a;
57 uiA = uA.ui;
58 exp = expF64UI( uiA );
59 sig = fracF64UI( uiA );
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 shiftDist = 0x433 - exp;
63 if ( 53 <= shiftDist ) {
64 if ( exact && (exp | sig) ) {
65 softfloat_exceptionFlags |= softfloat_flag_inexact;
66 }
67 return 0;
68 }
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 sign = signF64UI( uiA );
72 if ( sign ) goto invalid;
73 if ( shiftDist <= 0 ) {
74 if ( shiftDist < -11 ) goto invalid;
75 z = (sig | UINT64_C( 0x0010000000000000 ))<<-shiftDist;
76 } else {
77 sig |= UINT64_C( 0x0010000000000000 );
78 z = sig>>shiftDist;
79 if ( exact && (uint64_t) (sig<<(-shiftDist & 63)) ) {
80 softfloat_exceptionFlags |= softfloat_flag_inexact;
81 }
82 }
83 return z;
84 /*------------------------------------------------------------------------
85 *------------------------------------------------------------------------*/
86 invalid:
87 softfloat_raiseFlags( softfloat_flag_invalid );
88 return
89 (exp == 0x7FF) && sig ? ui64_fromNaN
90 : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
91
92}
93
deps/SoftFloat-3e/source/i32_to_extF80.c deleted-65
...@@ -1,65 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43extFloat80_t i32_to_extF80( int32_t a )
44{
45 uint_fast16_t uiZ64;
46 uint_fast32_t absA;
47 bool sign;
48 int_fast8_t shiftDist;
49 union { struct extFloat80M s; extFloat80_t f; } uZ;
50
51 uiZ64 = 0;
52 absA = 0;
53 if ( a ) {
54 sign = (a < 0);
55 absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a;
56 shiftDist = softfloat_countLeadingZeros32( absA );
57 uiZ64 = packToExtF80UI64( sign, 0x401E - shiftDist );
58 absA <<= shiftDist;
59 }
60 uZ.s.signExp = uiZ64;
61 uZ.s.signif = (uint_fast64_t) absA<<32;
62 return uZ.f;
63
64}
65
deps/SoftFloat-3e/source/i32_to_extF80M.c deleted-78
...@@ -1,78 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42#ifdef SOFTFLOAT_FAST_INT64
43
44void i32_to_extF80M( int32_t a, extFloat80_t *zPtr )
45{
46
47 *zPtr = i32_to_extF80( a );
48
49}
50
51#else
52
53void i32_to_extF80M( int32_t a, extFloat80_t *zPtr )
54{
55 struct extFloat80M *zSPtr;
56 uint_fast16_t uiZ64;
57 uint64_t sigZ;
58 bool sign;
59 uint32_t absA;
60 int_fast8_t shiftDist;
61
62 zSPtr = (struct extFloat80M *) zPtr;
63 uiZ64 = 0;
64 sigZ = 0;
65 if ( a ) {
66 sign = (a < 0);
67 absA = sign ? -(uint32_t) a : (uint32_t) a;
68 shiftDist = softfloat_countLeadingZeros32( absA );
69 uiZ64 = packToExtF80UI64( sign, 0x401E - shiftDist );
70 sigZ = (uint64_t) (absA<<shiftDist)<<32;
71 }
72 zSPtr->signExp = uiZ64;
73 zSPtr->signif = sigZ;
74
75}
76
77#endif
78
deps/SoftFloat-3e/source/i32_to_f128.c deleted-64
...@@ -1,64 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float128_t i32_to_f128( int32_t a )
43{
44 uint_fast64_t uiZ64;
45 bool sign;
46 uint_fast32_t absA;
47 int_fast8_t shiftDist;
48 union ui128_f128 uZ;
49
50 uiZ64 = 0;
51 if ( a ) {
52 sign = (a < 0);
53 absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a;
54 shiftDist = softfloat_countLeadingZeros32( absA ) + 17;
55 uiZ64 =
56 packToF128UI64(
57 sign, 0x402E - shiftDist, (uint_fast64_t) absA<<shiftDist );
58 }
59 uZ.ui.v64 = uiZ64;
60 uZ.ui.v0 = 0;
61 return uZ.f;
62
63}
64
deps/SoftFloat-3e/source/i32_to_f128M.c deleted-81
...@@ -1,81 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42#ifdef SOFTFLOAT_FAST_INT64
43
44void i32_to_f128M( int32_t a, float128_t *zPtr )
45{
46
47 *zPtr = i32_to_f128( a );
48
49}
50
51#else
52
53void i32_to_f128M( int32_t a, float128_t *zPtr )
54{
55 uint32_t *zWPtr;
56 uint32_t uiZ96, uiZ64;
57 bool sign;
58 uint32_t absA;
59 int_fast8_t shiftDist;
60 uint64_t normAbsA;
61
62 zWPtr = (uint32_t *) zPtr;
63 uiZ96 = 0;
64 uiZ64 = 0;
65 if ( a ) {
66 sign = (a < 0);
67 absA = sign ? -(uint32_t) a : (uint32_t) a;
68 shiftDist = softfloat_countLeadingZeros32( absA ) + 17;
69 normAbsA = (uint64_t) absA<<shiftDist;
70 uiZ96 = packToF128UI96( sign, 0x402E - shiftDist, normAbsA>>32 );
71 uiZ64 = normAbsA;
72 }
73 zWPtr[indexWord( 4, 3 )] = uiZ96;
74 zWPtr[indexWord( 4, 2 )] = uiZ64;
75 zWPtr[indexWord( 4, 1 )] = 0;
76 zWPtr[indexWord( 4, 0 )] = 0;
77
78}
79
80#endif
81
deps/SoftFloat-3e/source/i32_to_f16.c deleted-71
...@@ -1,71 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float16_t i32_to_f16( int32_t a )
44{
45 bool sign;
46 uint_fast32_t absA;
47 int_fast8_t shiftDist;
48 union ui16_f16 u;
49 uint_fast16_t sig;
50
51 sign = (a < 0);
52 absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a;
53 shiftDist = softfloat_countLeadingZeros32( absA ) - 21;
54 if ( 0 <= shiftDist ) {
55 u.ui =
56 a ? packToF16UI(
57 sign, 0x18 - shiftDist, (uint_fast16_t) absA<<shiftDist )
58 : 0;
59 return u.f;
60 } else {
61 shiftDist += 4;
62 sig =
63 (shiftDist < 0)
64 ? absA>>(-shiftDist)
65 | ((uint32_t) (absA<<(shiftDist & 31)) != 0)
66 : (uint_fast16_t) absA<<shiftDist;
67 return softfloat_roundPackToF16( sign, 0x1C - shiftDist, sig );
68 }
69
70}
71
deps/SoftFloat-3e/source/i32_to_f32.c deleted-58
...@@ -1,58 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float32_t i32_to_f32( int32_t a )
44{
45 bool sign;
46 union ui32_f32 uZ;
47 uint_fast32_t absA;
48
49 sign = (a < 0);
50 if ( ! (a & 0x7FFFFFFF) ) {
51 uZ.ui = sign ? packToF32UI( 1, 0x9E, 0 ) : 0;
52 return uZ.f;
53 }
54 absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a;
55 return softfloat_normRoundPackToF32( sign, 0x9C, absA );
56
57}
58
deps/SoftFloat-3e/source/i32_to_f64.c deleted-65
...@@ -1,65 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float64_t i32_to_f64( int32_t a )
44{
45 uint_fast64_t uiZ;
46 bool sign;
47 uint_fast32_t absA;
48 int_fast8_t shiftDist;
49 union ui64_f64 uZ;
50
51 if ( ! a ) {
52 uiZ = 0;
53 } else {
54 sign = (a < 0);
55 absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a;
56 shiftDist = softfloat_countLeadingZeros32( absA ) + 21;
57 uiZ =
58 packToF64UI(
59 sign, 0x432 - shiftDist, (uint_fast64_t) absA<<shiftDist );
60 }
61 uZ.ui = uiZ;
62 return uZ.f;
63
64}
65
deps/SoftFloat-3e/source/i64_to_extF80.c deleted-65
...@@ -1,65 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43extFloat80_t i64_to_extF80( int64_t a )
44{
45 uint_fast16_t uiZ64;
46 uint_fast64_t absA;
47 bool sign;
48 int_fast8_t shiftDist;
49 union { struct extFloat80M s; extFloat80_t f; } uZ;
50
51 uiZ64 = 0;
52 absA = 0;
53 if ( a ) {
54 sign = (a < 0);
55 absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a;
56 shiftDist = softfloat_countLeadingZeros64( absA );
57 uiZ64 = packToExtF80UI64( sign, 0x403E - shiftDist );
58 absA <<= shiftDist;
59 }
60 uZ.s.signExp = uiZ64;
61 uZ.s.signif = absA;
62 return uZ.f;
63
64}
65
deps/SoftFloat-3e/source/i64_to_extF80M.c deleted-78
...@@ -1,78 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42#ifdef SOFTFLOAT_FAST_INT64
43
44void i64_to_extF80M( int64_t a, extFloat80_t *zPtr )
45{
46
47 *zPtr = i64_to_extF80( a );
48
49}
50
51#else
52
53void i64_to_extF80M( int64_t a, extFloat80_t *zPtr )
54{
55 struct extFloat80M *zSPtr;
56 uint_fast16_t uiZ64;
57 uint64_t sigZ;
58 bool sign;
59 uint64_t absA;
60 int_fast8_t shiftDist;
61
62 zSPtr = (struct extFloat80M *) zPtr;
63 uiZ64 = 0;
64 sigZ = 0;
65 if ( a ) {
66 sign = (a < 0);
67 absA = sign ? -(uint64_t) a : (uint64_t) a;
68 shiftDist = softfloat_countLeadingZeros64( absA );
69 uiZ64 = packToExtF80UI64( sign, 0x403E - shiftDist );
70 sigZ = absA<<shiftDist;
71 }
72 zSPtr->signExp = uiZ64;
73 zSPtr->signif = sigZ;
74
75}
76
77#endif
78
deps/SoftFloat-3e/source/i64_to_f128.c deleted-72
...@@ -1,72 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float128_t i64_to_f128( int64_t a )
43{
44 uint_fast64_t uiZ64, uiZ0;
45 bool sign;
46 uint_fast64_t absA;
47 int_fast8_t shiftDist;
48 struct uint128 zSig;
49 union ui128_f128 uZ;
50
51 if ( ! a ) {
52 uiZ64 = 0;
53 uiZ0 = 0;
54 } else {
55 sign = (a < 0);
56 absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a;
57 shiftDist = softfloat_countLeadingZeros64( absA ) + 49;
58 if ( 64 <= shiftDist ) {
59 zSig.v64 = absA<<(shiftDist - 64);
60 zSig.v0 = 0;
61 } else {
62 zSig = softfloat_shortShiftLeft128( 0, absA, shiftDist );
63 }
64 uiZ64 = packToF128UI64( sign, 0x406E - shiftDist, zSig.v64 );
65 uiZ0 = zSig.v0;
66 }
67 uZ.ui.v64 = uiZ64;
68 uZ.ui.v0 = uiZ0;
69 return uZ.f;
70
71}
72
deps/SoftFloat-3e/source/i64_to_f128M.c deleted-92
...@@ -1,92 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42#ifdef SOFTFLOAT_FAST_INT64
43
44void i64_to_f128M( int64_t a, float128_t *zPtr )
45{
46
47 *zPtr = i64_to_f128( a );
48
49}
50
51#else
52
53void i64_to_f128M( int64_t a, float128_t *zPtr )
54{
55 uint32_t *zWPtr;
56 uint32_t uiZ96, uiZ64;
57 bool sign;
58 uint64_t absA;
59 uint_fast8_t shiftDist;
60 uint32_t *ptr;
61
62 zWPtr = (uint32_t *) zPtr;
63 uiZ96 = 0;
64 uiZ64 = 0;
65 zWPtr[indexWord( 4, 1 )] = 0;
66 zWPtr[indexWord( 4, 0 )] = 0;
67 if ( a ) {
68 sign = (a < 0);
69 absA = sign ? -(uint64_t) a : (uint64_t) a;
70 shiftDist = softfloat_countLeadingZeros64( absA ) + 17;
71 if ( shiftDist < 32 ) {
72 ptr = zWPtr + indexMultiwordHi( 4, 3 );
73 ptr[indexWord( 3, 2 )] = 0;
74 ptr[indexWord( 3, 1 )] = absA>>32;
75 ptr[indexWord( 3, 0 )] = absA;
76 softfloat_shortShiftLeft96M( ptr, shiftDist, ptr );
77 ptr[indexWordHi( 3 )] =
78 packToF128UI96(
79 sign, 0x404E - shiftDist, ptr[indexWordHi( 3 )] );
80 return;
81 }
82 absA <<= shiftDist - 32;
83 uiZ96 = packToF128UI96( sign, 0x404E - shiftDist, absA>>32 );
84 uiZ64 = absA;
85 }
86 zWPtr[indexWord( 4, 3 )] = uiZ96;
87 zWPtr[indexWord( 4, 2 )] = uiZ64;
88
89}
90
91#endif
92
deps/SoftFloat-3e/source/i64_to_f16.c deleted-70
...@@ -1,70 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float16_t i64_to_f16( int64_t a )
44{
45 bool sign;
46 uint_fast64_t absA;
47 int_fast8_t shiftDist;
48 union ui16_f16 u;
49 uint_fast16_t sig;
50
51 sign = (a < 0);
52 absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a;
53 shiftDist = softfloat_countLeadingZeros64( absA ) - 53;
54 if ( 0 <= shiftDist ) {
55 u.ui =
56 a ? packToF16UI(
57 sign, 0x18 - shiftDist, (uint_fast16_t) absA<<shiftDist )
58 : 0;
59 return u.f;
60 } else {
61 shiftDist += 4;
62 sig =
63 (shiftDist < 0)
64 ? softfloat_shortShiftRightJam64( absA, -shiftDist )
65 : (uint_fast16_t) absA<<shiftDist;
66 return softfloat_roundPackToF16( sign, 0x1C - shiftDist, sig );
67 }
68
69}
70
deps/SoftFloat-3e/source/i64_to_f32.c deleted-70
...@@ -1,70 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float32_t i64_to_f32( int64_t a )
44{
45 bool sign;
46 uint_fast64_t absA;
47 int_fast8_t shiftDist;
48 union ui32_f32 u;
49 uint_fast32_t sig;
50
51 sign = (a < 0);
52 absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a;
53 shiftDist = softfloat_countLeadingZeros64( absA ) - 40;
54 if ( 0 <= shiftDist ) {
55 u.ui =
56 a ? packToF32UI(
57 sign, 0x95 - shiftDist, (uint_fast32_t) absA<<shiftDist )
58 : 0;
59 return u.f;
60 } else {
61 shiftDist += 7;
62 sig =
63 (shiftDist < 0)
64 ? softfloat_shortShiftRightJam64( absA, -shiftDist )
65 : (uint_fast32_t) absA<<shiftDist;
66 return softfloat_roundPackToF32( sign, 0x9C - shiftDist, sig );
67 }
68
69}
70
deps/SoftFloat-3e/source/i64_to_f64.c deleted-58
...@@ -1,58 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float64_t i64_to_f64( int64_t a )
44{
45 bool sign;
46 union ui64_f64 uZ;
47 uint_fast64_t absA;
48
49 sign = (a < 0);
50 if ( ! (a & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) {
51 uZ.ui = sign ? packToF64UI( 1, 0x43E, 0 ) : 0;
52 return uZ.f;
53 }
54 absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a;
55 return softfloat_normRoundPackToF64( sign, 0x43C, absA );
56
57}
58
deps/SoftFloat-3e/source/include/internals.h deleted-278
...@@ -1,278 +0,0 @@
1
2/*============================================================================
3
4This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#ifndef internals_h
38#define internals_h 1
39
40#include <stdbool.h>
41#include <stdint.h>
42#include "primitives.h"
43#include "softfloat_types.h"
44
45union ui16_f16 { uint16_t ui; float16_t f; };
46union ui32_f32 { uint32_t ui; float32_t f; };
47union ui64_f64 { uint64_t ui; float64_t f; };
48
49#ifdef SOFTFLOAT_FAST_INT64
50union extF80M_extF80 { struct extFloat80M fM; extFloat80_t f; };
51union ui128_f128 { struct uint128 ui; float128_t f; };
52#endif
53
54enum {
55 softfloat_mulAdd_subC = 1,
56 softfloat_mulAdd_subProd = 2
57};
58
59/*----------------------------------------------------------------------------
60*----------------------------------------------------------------------------*/
61uint_fast32_t softfloat_roundToUI32( bool, uint_fast64_t, uint_fast8_t, bool );
62
63#ifdef SOFTFLOAT_FAST_INT64
64uint_fast64_t
65 softfloat_roundToUI64(
66 bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool );
67#else
68uint_fast64_t softfloat_roundMToUI64( bool, uint32_t *, uint_fast8_t, bool );
69#endif
70
71int_fast32_t softfloat_roundToI32( bool, uint_fast64_t, uint_fast8_t, bool );
72
73#ifdef SOFTFLOAT_FAST_INT64
74int_fast64_t
75 softfloat_roundToI64(
76 bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool );
77#else
78int_fast64_t softfloat_roundMToI64( bool, uint32_t *, uint_fast8_t, bool );
79#endif
80
81/*----------------------------------------------------------------------------
82*----------------------------------------------------------------------------*/
83#define signF16UI( a ) ((bool) ((uint16_t) (a)>>15))
84#define expF16UI( a ) ((int_fast8_t) ((a)>>10) & 0x1F)
85#define fracF16UI( a ) ((a) & 0x03FF)
86#define packToF16UI( sign, exp, sig ) (((uint16_t) (sign)<<15) + ((uint16_t) (exp)<<10) + (sig))
87
88#define isNaNF16UI( a ) (((~(a) & 0x7C00) == 0) && ((a) & 0x03FF))
89
90struct exp8_sig16 { int_fast8_t exp; uint_fast16_t sig; };
91struct exp8_sig16 softfloat_normSubnormalF16Sig( uint_fast16_t );
92
93float16_t softfloat_roundPackToF16( bool, int_fast16_t, uint_fast16_t );
94float16_t softfloat_normRoundPackToF16( bool, int_fast16_t, uint_fast16_t );
95
96float16_t softfloat_addMagsF16( uint_fast16_t, uint_fast16_t );
97float16_t softfloat_subMagsF16( uint_fast16_t, uint_fast16_t );
98float16_t
99 softfloat_mulAddF16(
100 uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_fast8_t );
101
102/*----------------------------------------------------------------------------
103*----------------------------------------------------------------------------*/
104#define signF32UI( a ) ((bool) ((uint32_t) (a)>>31))
105#define expF32UI( a ) ((int_fast16_t) ((a)>>23) & 0xFF)
106#define fracF32UI( a ) ((a) & 0x007FFFFF)
107#define packToF32UI( sign, exp, sig ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig))
108
109#define isNaNF32UI( a ) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF))
110
111struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; };
112struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t );
113
114float32_t softfloat_roundPackToF32( bool, int_fast16_t, uint_fast32_t );
115float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t );
116
117float32_t softfloat_addMagsF32( uint_fast32_t, uint_fast32_t );
118float32_t softfloat_subMagsF32( uint_fast32_t, uint_fast32_t );
119float32_t
120 softfloat_mulAddF32(
121 uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t );
122
123/*----------------------------------------------------------------------------
124*----------------------------------------------------------------------------*/
125#define signF64UI( a ) ((bool) ((uint64_t) (a)>>63))
126#define expF64UI( a ) ((int_fast16_t) ((a)>>52) & 0x7FF)
127#define fracF64UI( a ) ((a) & UINT64_C( 0x000FFFFFFFFFFFFF ))
128#define packToF64UI( sign, exp, sig ) ((uint64_t) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<52) + (sig)))
129
130#define isNaNF64UI( a ) (((~(a) & UINT64_C( 0x7FF0000000000000 )) == 0) && ((a) & UINT64_C( 0x000FFFFFFFFFFFFF )))
131
132struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; };
133struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t );
134
135float64_t softfloat_roundPackToF64( bool, int_fast16_t, uint_fast64_t );
136float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t );
137
138float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool );
139float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool );
140float64_t
141 softfloat_mulAddF64(
142 uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
143
144/*----------------------------------------------------------------------------
145*----------------------------------------------------------------------------*/
146#define signExtF80UI64( a64 ) ((bool) ((uint16_t) (a64)>>15))
147#define expExtF80UI64( a64 ) ((a64) & 0x7FFF)
148#define packToExtF80UI64( sign, exp ) ((uint_fast16_t) (sign)<<15 | (exp))
149
150#define isNaNExtF80UI( a64, a0 ) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
151
152#ifdef SOFTFLOAT_FAST_INT64
153
154/*----------------------------------------------------------------------------
155*----------------------------------------------------------------------------*/
156
157struct exp32_sig64 { int_fast32_t exp; uint64_t sig; };
158struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t );
159
160extFloat80_t
161 softfloat_roundPackToExtF80(
162 bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
163extFloat80_t
164 softfloat_normRoundPackToExtF80(
165 bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
166
167extFloat80_t
168 softfloat_addMagsExtF80(
169 uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool );
170extFloat80_t
171 softfloat_subMagsExtF80(
172 uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool );
173
174/*----------------------------------------------------------------------------
175*----------------------------------------------------------------------------*/
176#define signF128UI64( a64 ) ((bool) ((uint64_t) (a64)>>63))
177#define expF128UI64( a64 ) ((int_fast32_t) ((a64)>>48) & 0x7FFF)
178#define fracF128UI64( a64 ) ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF ))
179#define packToF128UI64( sign, exp, sig64 ) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<48) + (sig64))
180
181#define isNaNF128UI( a64, a0 ) (((~(a64) & UINT64_C( 0x7FFF000000000000 )) == 0) && (a0 || ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF ))))
182
183struct exp32_sig128 { int_fast32_t exp; struct uint128 sig; };
184struct exp32_sig128
185 softfloat_normSubnormalF128Sig( uint_fast64_t, uint_fast64_t );
186
187float128_t
188 softfloat_roundPackToF128(
189 bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t );
190float128_t
191 softfloat_normRoundPackToF128(
192 bool, int_fast32_t, uint_fast64_t, uint_fast64_t );
193
194float128_t
195 softfloat_addMagsF128(
196 uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
197float128_t
198 softfloat_subMagsF128(
199 uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
200float128_t
201 softfloat_mulAddF128(
202 uint_fast64_t,
203 uint_fast64_t,
204 uint_fast64_t,
205 uint_fast64_t,
206 uint_fast64_t,
207 uint_fast64_t,
208 uint_fast8_t
209 );
210
211#else
212
213/*----------------------------------------------------------------------------
214*----------------------------------------------------------------------------*/
215
216bool
217 softfloat_tryPropagateNaNExtF80M(
218 const struct extFloat80M *,
219 const struct extFloat80M *,
220 struct extFloat80M *
221 );
222void softfloat_invalidExtF80M( struct extFloat80M * );
223
224int softfloat_normExtF80SigM( uint64_t * );
225
226void
227 softfloat_roundPackMToExtF80M(
228 bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * );
229void
230 softfloat_normRoundPackMToExtF80M(
231 bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * );
232
233void
234 softfloat_addExtF80M(
235 const struct extFloat80M *,
236 const struct extFloat80M *,
237 struct extFloat80M *,
238 bool
239 );
240
241int
242 softfloat_compareNonnormExtF80M(
243 const struct extFloat80M *, const struct extFloat80M * );
244
245/*----------------------------------------------------------------------------
246*----------------------------------------------------------------------------*/
247#define signF128UI96( a96 ) ((bool) ((uint32_t) (a96)>>31))
248#define expF128UI96( a96 ) ((int32_t) ((a96)>>16) & 0x7FFF)
249#define fracF128UI96( a96 ) ((a96) & 0x0000FFFF)
250#define packToF128UI96( sign, exp, sig96 ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<16) + (sig96))
251
252bool softfloat_isNaNF128M( const uint32_t * );
253
254bool
255 softfloat_tryPropagateNaNF128M(
256 const uint32_t *, const uint32_t *, uint32_t * );
257void softfloat_invalidF128M( uint32_t * );
258
259int softfloat_shiftNormSigF128M( const uint32_t *, uint_fast8_t, uint32_t * );
260
261void softfloat_roundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * );
262void softfloat_normRoundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * );
263
264void
265 softfloat_addF128M( const uint32_t *, const uint32_t *, uint32_t *, bool );
266void
267 softfloat_mulAddF128M(
268 const uint32_t *,
269 const uint32_t *,
270 const uint32_t *,
271 uint32_t *,
272 uint_fast8_t
273 );
274
275#endif
276
277#endif
278
deps/SoftFloat-3e/source/include/opts-GCC.h deleted-114
...@@ -1,114 +0,0 @@
1
2/*============================================================================
3
4This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2017 The Regents of the University of California. All rights
8reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#ifndef opts_GCC_h
38#define opts_GCC_h 1
39
40#ifdef INLINE
41
42#include <stdint.h>
43#include "primitiveTypes.h"
44
45#ifdef SOFTFLOAT_BUILTIN_CLZ
46
47INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a )
48 { return a ? __builtin_clz( a ) - 16 : 16; }
49#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16
50
51INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a )
52 { return a ? __builtin_clz( a ) : 32; }
53#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32
54
55INLINE uint_fast8_t softfloat_countLeadingZeros64( uint64_t a )
56 { return a ? __builtin_clzll( a ) : 64; }
57#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64
58
59#endif
60
61#ifdef SOFTFLOAT_INTRINSIC_INT128
62
63INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b )
64{
65 union { unsigned __int128 ui; struct uint128 s; } uZ;
66 uZ.ui = (unsigned __int128) a * ((uint_fast64_t) b<<32);
67 return uZ.s;
68}
69#define softfloat_mul64ByShifted32To128 softfloat_mul64ByShifted32To128
70
71INLINE struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b )
72{
73 union { unsigned __int128 ui; struct uint128 s; } uZ;
74 uZ.ui = (unsigned __int128) a * b;
75 return uZ.s;
76}
77#define softfloat_mul64To128 softfloat_mul64To128
78
79INLINE
80struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b )
81{
82 union { unsigned __int128 ui; struct uint128 s; } uZ;
83 uZ.ui = ((unsigned __int128) a64<<64 | a0) * b;
84 return uZ.s;
85}
86#define softfloat_mul128By32 softfloat_mul128By32
87
88INLINE
89void
90 softfloat_mul128To256M(
91 uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr )
92{
93 unsigned __int128 z0, mid1, mid, z128;
94 z0 = (unsigned __int128) a0 * b0;
95 mid1 = (unsigned __int128) a64 * b0;
96 mid = mid1 + (unsigned __int128) a0 * b64;
97 z128 = (unsigned __int128) a64 * b64;
98 z128 += (unsigned __int128) (mid < mid1)<<64 | mid>>64;
99 mid <<= 64;
100 z0 += mid;
101 z128 += (z0 < mid);
102 zPtr[indexWord( 4, 0 )] = z0;
103 zPtr[indexWord( 4, 1 )] = z0>>64;
104 zPtr[indexWord( 4, 2 )] = z128;
105 zPtr[indexWord( 4, 3 )] = z128>>64;
106}
107#define softfloat_mul128To256M softfloat_mul128To256M
108
109#endif
110
111#endif
112
113#endif
114
deps/SoftFloat-3e/source/include/primitiveTypes.h deleted-86
...@@ -1,86 +0,0 @@
1
2/*============================================================================
3
4This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#ifndef primitiveTypes_h
38#define primitiveTypes_h 1
39
40#include "platform.h"
41#include <stdint.h>
42
43#ifdef SOFTFLOAT_FAST_INT64
44
45#ifdef LITTLEENDIAN
46struct uint128 { uint64_t v0, v64; };
47struct uint64_extra { uint64_t extra, v; };
48struct uint128_extra { uint64_t extra; struct uint128 v; };
49#else
50struct uint128 { uint64_t v64, v0; };
51struct uint64_extra { uint64_t v, extra; };
52struct uint128_extra { struct uint128 v; uint64_t extra; };
53#endif
54
55#endif
56
57/*----------------------------------------------------------------------------
58| These macros are used to isolate the differences in word order between big-
59| endian and little-endian platforms.
60*----------------------------------------------------------------------------*/
61#ifdef LITTLEENDIAN
62#define wordIncr 1
63#define indexWord( total, n ) (n)
64#define indexWordHi( total ) ((total) - 1)
65#define indexWordLo( total ) 0
66#define indexMultiword( total, m, n ) (n)
67#define indexMultiwordHi( total, n ) ((total) - (n))
68#define indexMultiwordLo( total, n ) 0
69#define indexMultiwordHiBut( total, n ) (n)
70#define indexMultiwordLoBut( total, n ) 0
71#define INIT_UINTM4( v3, v2, v1, v0 ) { v0, v1, v2, v3 }
72#else
73#define wordIncr -1
74#define indexWord( total, n ) ((total) - 1 - (n))
75#define indexWordHi( total ) 0
76#define indexWordLo( total ) ((total) - 1)
77#define indexMultiword( total, m, n ) ((total) - 1 - (m))
78#define indexMultiwordHi( total, n ) 0
79#define indexMultiwordLo( total, n ) ((total) - (n))
80#define indexMultiwordHiBut( total, n ) 0
81#define indexMultiwordLoBut( total, n ) (n)
82#define INIT_UINTM4( v3, v2, v1, v0 ) { v3, v2, v1, v0 }
83#endif
84
85#endif
86
deps/SoftFloat-3e/source/include/primitives.h deleted-1160
...@@ -1,1160 +0,0 @@
1
2/*============================================================================
3
4This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#ifndef primitives_h
38#define primitives_h 1
39
40#include <stdbool.h>
41#include <stdint.h>
42#include "primitiveTypes.h"
43
44#ifndef softfloat_shortShiftRightJam64
45/*----------------------------------------------------------------------------
46| Shifts 'a' right by the number of bits given in 'dist', which must be in
47| the range 1 to 63. If any nonzero bits are shifted off, they are "jammed"
48| into the least-significant bit of the shifted value by setting the least-
49| significant bit to 1. This shifted-and-jammed value is returned.
50*----------------------------------------------------------------------------*/
51#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
52INLINE
53uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist )
54 { return a>>dist | ((a & (((uint_fast64_t) 1<<dist) - 1)) != 0); }
55#else
56uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist );
57#endif
58#endif
59
60#ifndef softfloat_shiftRightJam32
61/*----------------------------------------------------------------------------
62| Shifts 'a' right by the number of bits given in 'dist', which must not
63| be zero. If any nonzero bits are shifted off, they are "jammed" into the
64| least-significant bit of the shifted value by setting the least-significant
65| bit to 1. This shifted-and-jammed value is returned.
66| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
67| greater than 32, the result will be either 0 or 1, depending on whether 'a'
68| is zero or nonzero.
69*----------------------------------------------------------------------------*/
70#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
71INLINE uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist )
72{
73 return
74 (dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0);
75}
76#else
77uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist );
78#endif
79#endif
80
81#ifndef softfloat_shiftRightJam64
82/*----------------------------------------------------------------------------
83| Shifts 'a' right by the number of bits given in 'dist', which must not
84| be zero. If any nonzero bits are shifted off, they are "jammed" into the
85| least-significant bit of the shifted value by setting the least-significant
86| bit to 1. This shifted-and-jammed value is returned.
87| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
88| greater than 64, the result will be either 0 or 1, depending on whether 'a'
89| is zero or nonzero.
90*----------------------------------------------------------------------------*/
91#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
92INLINE uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist )
93{
94 return
95 (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0);
96}
97#else
98uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist );
99#endif
100#endif
101
102/*----------------------------------------------------------------------------
103| A constant table that translates an 8-bit unsigned integer (the array index)
104| into the number of leading 0 bits before the most-significant 1 of that
105| integer. For integer zero (index 0), the corresponding table element is 8.
106*----------------------------------------------------------------------------*/
107extern const uint_least8_t softfloat_countLeadingZeros8[256];
108
109#ifndef softfloat_countLeadingZeros16
110/*----------------------------------------------------------------------------
111| Returns the number of leading 0 bits before the most-significant 1 bit of
112| 'a'. If 'a' is zero, 16 is returned.
113*----------------------------------------------------------------------------*/
114#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
115INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a )
116{
117 uint_fast8_t count = 8;
118 if ( 0x100 <= a ) {
119 count = 0;
120 a >>= 8;
121 }
122 count += softfloat_countLeadingZeros8[a];
123 return count;
124}
125#else
126uint_fast8_t softfloat_countLeadingZeros16( uint16_t a );
127#endif
128#endif
129
130#ifndef softfloat_countLeadingZeros32
131/*----------------------------------------------------------------------------
132| Returns the number of leading 0 bits before the most-significant 1 bit of
133| 'a'. If 'a' is zero, 32 is returned.
134*----------------------------------------------------------------------------*/
135#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
136INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a )
137{
138 uint_fast8_t count = 0;
139 if ( a < 0x10000 ) {
140 count = 16;
141 a <<= 16;
142 }
143 if ( a < 0x1000000 ) {
144 count += 8;
145 a <<= 8;
146 }
147 count += softfloat_countLeadingZeros8[a>>24];
148 return count;
149}
150#else
151uint_fast8_t softfloat_countLeadingZeros32( uint32_t a );
152#endif
153#endif
154
155#ifndef softfloat_countLeadingZeros64
156/*----------------------------------------------------------------------------
157| Returns the number of leading 0 bits before the most-significant 1 bit of
158| 'a'. If 'a' is zero, 64 is returned.
159*----------------------------------------------------------------------------*/
160uint_fast8_t softfloat_countLeadingZeros64( uint64_t a );
161#endif
162
163extern const uint16_t softfloat_approxRecip_1k0s[16];
164extern const uint16_t softfloat_approxRecip_1k1s[16];
165
166#ifndef softfloat_approxRecip32_1
167/*----------------------------------------------------------------------------
168| Returns an approximation to the reciprocal of the number represented by 'a',
169| where 'a' is interpreted as an unsigned fixed-point number with one integer
170| bit and 31 fraction bits. The 'a' input must be "normalized", meaning that
171| its most-significant bit (bit 31) must be 1. Thus, if A is the value of
172| the fixed-point interpretation of 'a', then 1 <= A < 2. The returned value
173| is interpreted as a pure unsigned fraction, having no integer bits and 32
174| fraction bits. The approximation returned is never greater than the true
175| reciprocal 1/A, and it differs from the true reciprocal by at most 2.006 ulp
176| (units in the last place).
177*----------------------------------------------------------------------------*/
178#ifdef SOFTFLOAT_FAST_DIV64TO32
179#define softfloat_approxRecip32_1( a ) ((uint32_t) (UINT64_C( 0x7FFFFFFFFFFFFFFF ) / (uint32_t) (a)))
180#else
181uint32_t softfloat_approxRecip32_1( uint32_t a );
182#endif
183#endif
184
185extern const uint16_t softfloat_approxRecipSqrt_1k0s[16];
186extern const uint16_t softfloat_approxRecipSqrt_1k1s[16];
187
188#ifndef softfloat_approxRecipSqrt32_1
189/*----------------------------------------------------------------------------
190| Returns an approximation to the reciprocal of the square root of the number
191| represented by 'a', where 'a' is interpreted as an unsigned fixed-point
192| number either with one integer bit and 31 fraction bits or with two integer
193| bits and 30 fraction bits. The format of 'a' is determined by 'oddExpA',
194| which must be either 0 or 1. If 'oddExpA' is 1, 'a' is interpreted as
195| having one integer bit, and if 'oddExpA' is 0, 'a' is interpreted as having
196| two integer bits. The 'a' input must be "normalized", meaning that its
197| most-significant bit (bit 31) must be 1. Thus, if A is the value of the
198| fixed-point interpretation of 'a', it follows that 1 <= A < 2 when 'oddExpA'
199| is 1, and 2 <= A < 4 when 'oddExpA' is 0.
200| The returned value is interpreted as a pure unsigned fraction, having
201| no integer bits and 32 fraction bits. The approximation returned is never
202| greater than the true reciprocal 1/sqrt(A), and it differs from the true
203| reciprocal by at most 2.06 ulp (units in the last place). The approximation
204| returned is also always within the range 0.5 to 1; thus, the most-
205| significant bit of the result is always set.
206*----------------------------------------------------------------------------*/
207uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a );
208#endif
209
210#ifdef SOFTFLOAT_FAST_INT64
211
212/*----------------------------------------------------------------------------
213| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is
214| defined.
215*----------------------------------------------------------------------------*/
216
217#ifndef softfloat_eq128
218/*----------------------------------------------------------------------------
219| Returns true if the 128-bit unsigned integer formed by concatenating 'a64'
220| and 'a0' is equal to the 128-bit unsigned integer formed by concatenating
221| 'b64' and 'b0'.
222*----------------------------------------------------------------------------*/
223#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
224INLINE
225bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
226 { return (a64 == b64) && (a0 == b0); }
227#else
228bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
229#endif
230#endif
231
232#ifndef softfloat_le128
233/*----------------------------------------------------------------------------
234| Returns true if the 128-bit unsigned integer formed by concatenating 'a64'
235| and 'a0' is less than or equal to the 128-bit unsigned integer formed by
236| concatenating 'b64' and 'b0'.
237*----------------------------------------------------------------------------*/
238#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
239INLINE
240bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
241 { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); }
242#else
243bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
244#endif
245#endif
246
247#ifndef softfloat_lt128
248/*----------------------------------------------------------------------------
249| Returns true if the 128-bit unsigned integer formed by concatenating 'a64'
250| and 'a0' is less than the 128-bit unsigned integer formed by concatenating
251| 'b64' and 'b0'.
252*----------------------------------------------------------------------------*/
253#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
254INLINE
255bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
256 { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); }
257#else
258bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
259#endif
260#endif
261
262#ifndef softfloat_shortShiftLeft128
263/*----------------------------------------------------------------------------
264| Shifts the 128 bits formed by concatenating 'a64' and 'a0' left by the
265| number of bits given in 'dist', which must be in the range 1 to 63.
266*----------------------------------------------------------------------------*/
267#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
268INLINE
269struct uint128
270 softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
271{
272 struct uint128 z;
273 z.v64 = a64<<dist | a0>>(-dist & 63);
274 z.v0 = a0<<dist;
275 return z;
276}
277#else
278struct uint128
279 softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
280#endif
281#endif
282
283#ifndef softfloat_shortShiftRight128
284/*----------------------------------------------------------------------------
285| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the
286| number of bits given in 'dist', which must be in the range 1 to 63.
287*----------------------------------------------------------------------------*/
288#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
289INLINE
290struct uint128
291 softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
292{
293 struct uint128 z;
294 z.v64 = a64>>dist;
295 z.v0 = a64<<(-dist & 63) | a0>>dist;
296 return z;
297}
298#else
299struct uint128
300 softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
301#endif
302#endif
303
304#ifndef softfloat_shortShiftRightJam64Extra
305/*----------------------------------------------------------------------------
306| This function is the same as 'softfloat_shiftRightJam64Extra' (below),
307| except that 'dist' must be in the range 1 to 63.
308*----------------------------------------------------------------------------*/
309#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
310INLINE
311struct uint64_extra
312 softfloat_shortShiftRightJam64Extra(
313 uint64_t a, uint64_t extra, uint_fast8_t dist )
314{
315 struct uint64_extra z;
316 z.v = a>>dist;
317 z.extra = a<<(-dist & 63) | (extra != 0);
318 return z;
319}
320#else
321struct uint64_extra
322 softfloat_shortShiftRightJam64Extra(
323 uint64_t a, uint64_t extra, uint_fast8_t dist );
324#endif
325#endif
326
327#ifndef softfloat_shortShiftRightJam128
328/*----------------------------------------------------------------------------
329| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the
330| number of bits given in 'dist', which must be in the range 1 to 63. If any
331| nonzero bits are shifted off, they are "jammed" into the least-significant
332| bit of the shifted value by setting the least-significant bit to 1. This
333| shifted-and-jammed value is returned.
334*----------------------------------------------------------------------------*/
335#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
336INLINE
337struct uint128
338 softfloat_shortShiftRightJam128(
339 uint64_t a64, uint64_t a0, uint_fast8_t dist )
340{
341 uint_fast8_t negDist = -dist;
342 struct uint128 z;
343 z.v64 = a64>>dist;
344 z.v0 =
345 a64<<(negDist & 63) | a0>>dist
346 | ((uint64_t) (a0<<(negDist & 63)) != 0);
347 return z;
348}
349#else
350struct uint128
351 softfloat_shortShiftRightJam128(
352 uint64_t a64, uint64_t a0, uint_fast8_t dist );
353#endif
354#endif
355
356#ifndef softfloat_shortShiftRightJam128Extra
357/*----------------------------------------------------------------------------
358| This function is the same as 'softfloat_shiftRightJam128Extra' (below),
359| except that 'dist' must be in the range 1 to 63.
360*----------------------------------------------------------------------------*/
361#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
362INLINE
363struct uint128_extra
364 softfloat_shortShiftRightJam128Extra(
365 uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist )
366{
367 uint_fast8_t negDist = -dist;
368 struct uint128_extra z;
369 z.v.v64 = a64>>dist;
370 z.v.v0 = a64<<(negDist & 63) | a0>>dist;
371 z.extra = a0<<(negDist & 63) | (extra != 0);
372 return z;
373}
374#else
375struct uint128_extra
376 softfloat_shortShiftRightJam128Extra(
377 uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist );
378#endif
379#endif
380
381#ifndef softfloat_shiftRightJam64Extra
382/*----------------------------------------------------------------------------
383| Shifts the 128 bits formed by concatenating 'a' and 'extra' right by 64
384| _plus_ the number of bits given in 'dist', which must not be zero. This
385| shifted value is at most 64 nonzero bits and is returned in the 'v' field
386| of the 'struct uint64_extra' result. The 64-bit 'extra' field of the result
387| contains a value formed as follows from the bits that were shifted off: The
388| _last_ bit shifted off is the most-significant bit of the 'extra' field, and
389| the other 63 bits of the 'extra' field are all zero if and only if _all_but_
390| _the_last_ bits shifted off were all zero.
391| (This function makes more sense if 'a' and 'extra' are considered to form
392| an unsigned fixed-point number with binary point between 'a' and 'extra'.
393| This fixed-point value is shifted right by the number of bits given in
394| 'dist', and the integer part of this shifted value is returned in the 'v'
395| field of the result. The fractional part of the shifted value is modified
396| as described above and returned in the 'extra' field of the result.)
397*----------------------------------------------------------------------------*/
398#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL)
399INLINE
400struct uint64_extra
401 softfloat_shiftRightJam64Extra(
402 uint64_t a, uint64_t extra, uint_fast32_t dist )
403{
404 struct uint64_extra z;
405 if ( dist < 64 ) {
406 z.v = a>>dist;
407 z.extra = a<<(-dist & 63);
408 } else {
409 z.v = 0;
410 z.extra = (dist == 64) ? a : (a != 0);
411 }
412 z.extra |= (extra != 0);
413 return z;
414}
415#else
416struct uint64_extra
417 softfloat_shiftRightJam64Extra(
418 uint64_t a, uint64_t extra, uint_fast32_t dist );
419#endif
420#endif
421
422#ifndef softfloat_shiftRightJam128
423/*----------------------------------------------------------------------------
424| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the
425| number of bits given in 'dist', which must not be zero. If any nonzero bits
426| are shifted off, they are "jammed" into the least-significant bit of the
427| shifted value by setting the least-significant bit to 1. This shifted-and-
428| jammed value is returned.
429| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
430| greater than 128, the result will be either 0 or 1, depending on whether the
431| original 128 bits are all zeros.
432*----------------------------------------------------------------------------*/
433struct uint128
434 softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t dist );
435#endif
436
437#ifndef softfloat_shiftRightJam128Extra
438/*----------------------------------------------------------------------------
439| Shifts the 192 bits formed by concatenating 'a64', 'a0', and 'extra' right
440| by 64 _plus_ the number of bits given in 'dist', which must not be zero.
441| This shifted value is at most 128 nonzero bits and is returned in the 'v'
442| field of the 'struct uint128_extra' result. The 64-bit 'extra' field of the
443| result contains a value formed as follows from the bits that were shifted
444| off: The _last_ bit shifted off is the most-significant bit of the 'extra'
445| field, and the other 63 bits of the 'extra' field are all zero if and only
446| if _all_but_the_last_ bits shifted off were all zero.
447| (This function makes more sense if 'a64', 'a0', and 'extra' are considered
448| to form an unsigned fixed-point number with binary point between 'a0' and
449| 'extra'. This fixed-point value is shifted right by the number of bits
450| given in 'dist', and the integer part of this shifted value is returned
451| in the 'v' field of the result. The fractional part of the shifted value
452| is modified as described above and returned in the 'extra' field of the
453| result.)
454*----------------------------------------------------------------------------*/
455struct uint128_extra
456 softfloat_shiftRightJam128Extra(
457 uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist );
458#endif
459
460#ifndef softfloat_shiftRightJam256M
461/*----------------------------------------------------------------------------
462| Shifts the 256-bit unsigned integer pointed to by 'aPtr' right by the number
463| of bits given in 'dist', which must not be zero. If any nonzero bits are
464| shifted off, they are "jammed" into the least-significant bit of the shifted
465| value by setting the least-significant bit to 1. This shifted-and-jammed
466| value is stored at the location pointed to by 'zPtr'. Each of 'aPtr' and
467| 'zPtr' points to an array of four 64-bit elements that concatenate in the
468| platform's normal endian order to form a 256-bit integer.
469| The value of 'dist' can be arbitrarily large. In particular, if 'dist'
470| is greater than 256, the stored result will be either 0 or 1, depending on
471| whether the original 256 bits are all zeros.
472*----------------------------------------------------------------------------*/
473void
474 softfloat_shiftRightJam256M(
475 const uint64_t *aPtr, uint_fast32_t dist, uint64_t *zPtr );
476#endif
477
478#ifndef softfloat_add128
479/*----------------------------------------------------------------------------
480| Returns the sum of the 128-bit integer formed by concatenating 'a64' and
481| 'a0' and the 128-bit integer formed by concatenating 'b64' and 'b0'. The
482| addition is modulo 2^128, so any carry out is lost.
483*----------------------------------------------------------------------------*/
484#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
485INLINE
486struct uint128
487 softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
488{
489 struct uint128 z;
490 z.v0 = a0 + b0;
491 z.v64 = a64 + b64 + (z.v0 < a0);
492 return z;
493}
494#else
495struct uint128
496 softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
497#endif
498#endif
499
500#ifndef softfloat_add256M
501/*----------------------------------------------------------------------------
502| Adds the two 256-bit integers pointed to by 'aPtr' and 'bPtr'. The addition
503| is modulo 2^256, so any carry out is lost. The sum is stored at the
504| location pointed to by 'zPtr'. Each of 'aPtr', 'bPtr', and 'zPtr' points to
505| an array of four 64-bit elements that concatenate in the platform's normal
506| endian order to form a 256-bit integer.
507*----------------------------------------------------------------------------*/
508void
509 softfloat_add256M(
510 const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr );
511#endif
512
513#ifndef softfloat_sub128
514/*----------------------------------------------------------------------------
515| Returns the difference of the 128-bit integer formed by concatenating 'a64'
516| and 'a0' and the 128-bit integer formed by concatenating 'b64' and 'b0'.
517| The subtraction is modulo 2^128, so any borrow out (carry out) is lost.
518*----------------------------------------------------------------------------*/
519#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
520INLINE
521struct uint128
522 softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
523{
524 struct uint128 z;
525 z.v0 = a0 - b0;
526 z.v64 = a64 - b64;
527 z.v64 -= (a0 < b0);
528 return z;
529}
530#else
531struct uint128
532 softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
533#endif
534#endif
535
536#ifndef softfloat_sub256M
537/*----------------------------------------------------------------------------
538| Subtracts the 256-bit integer pointed to by 'bPtr' from the 256-bit integer
539| pointed to by 'aPtr'. The addition is modulo 2^256, so any borrow out
540| (carry out) is lost. The difference is stored at the location pointed to
541| by 'zPtr'. Each of 'aPtr', 'bPtr', and 'zPtr' points to an array of four
542| 64-bit elements that concatenate in the platform's normal endian order to
543| form a 256-bit integer.
544*----------------------------------------------------------------------------*/
545void
546 softfloat_sub256M(
547 const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr );
548#endif
549
550#ifndef softfloat_mul64ByShifted32To128
551/*----------------------------------------------------------------------------
552| Returns the 128-bit product of 'a', 'b', and 2^32.
553*----------------------------------------------------------------------------*/
554#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
555INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b )
556{
557 uint_fast64_t mid;
558 struct uint128 z;
559 mid = (uint_fast64_t) (uint32_t) a * b;
560 z.v0 = mid<<32;
561 z.v64 = (uint_fast64_t) (uint32_t) (a>>32) * b + (mid>>32);
562 return z;
563}
564#else
565struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b );
566#endif
567#endif
568
569#ifndef softfloat_mul64To128
570/*----------------------------------------------------------------------------
571| Returns the 128-bit product of 'a' and 'b'.
572*----------------------------------------------------------------------------*/
573struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b );
574#endif
575
576#ifndef softfloat_mul128By32
577/*----------------------------------------------------------------------------
578| Returns the product of the 128-bit integer formed by concatenating 'a64' and
579| 'a0', multiplied by 'b'. The multiplication is modulo 2^128; any overflow
580| bits are discarded.
581*----------------------------------------------------------------------------*/
582#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL)
583INLINE
584struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b )
585{
586 struct uint128 z;
587 uint_fast64_t mid;
588 uint_fast32_t carry;
589 z.v0 = a0 * b;
590 mid = (uint_fast64_t) (uint32_t) (a0>>32) * b;
591 carry = (uint32_t) ((uint_fast32_t) (z.v0>>32) - (uint_fast32_t) mid);
592 z.v64 = a64 * b + (uint_fast32_t) ((mid + carry)>>32);
593 return z;
594}
595#else
596struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b );
597#endif
598#endif
599
600#ifndef softfloat_mul128To256M
601/*----------------------------------------------------------------------------
602| Multiplies the 128-bit unsigned integer formed by concatenating 'a64' and
603| 'a0' by the 128-bit unsigned integer formed by concatenating 'b64' and
604| 'b0'. The 256-bit product is stored at the location pointed to by 'zPtr'.
605| Argument 'zPtr' points to an array of four 64-bit elements that concatenate
606| in the platform's normal endian order to form a 256-bit integer.
607*----------------------------------------------------------------------------*/
608void
609 softfloat_mul128To256M(
610 uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr );
611#endif
612
613#else
614
615/*----------------------------------------------------------------------------
616| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is not
617| defined.
618*----------------------------------------------------------------------------*/
619
620#ifndef softfloat_compare96M
621/*----------------------------------------------------------------------------
622| Compares the two 96-bit unsigned integers pointed to by 'aPtr' and 'bPtr'.
623| Returns -1 if the first integer (A) is less than the second (B); returns 0
624| if the two integers are equal; and returns +1 if the first integer (A)
625| is greater than the second (B). (The result is thus the signum of A - B.)
626| Each of 'aPtr' and 'bPtr' points to an array of three 32-bit elements that
627| concatenate in the platform's normal endian order to form a 96-bit integer.
628*----------------------------------------------------------------------------*/
629int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr );
630#endif
631
632#ifndef softfloat_compare128M
633/*----------------------------------------------------------------------------
634| Compares the two 128-bit unsigned integers pointed to by 'aPtr' and 'bPtr'.
635| Returns -1 if the first integer (A) is less than the second (B); returns 0
636| if the two integers are equal; and returns +1 if the first integer (A)
637| is greater than the second (B). (The result is thus the signum of A - B.)
638| Each of 'aPtr' and 'bPtr' points to an array of four 32-bit elements that
639| concatenate in the platform's normal endian order to form a 128-bit integer.
640*----------------------------------------------------------------------------*/
641int_fast8_t
642 softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr );
643#endif
644
645#ifndef softfloat_shortShiftLeft64To96M
646/*----------------------------------------------------------------------------
647| Extends 'a' to 96 bits and shifts the value left by the number of bits given
648| in 'dist', which must be in the range 1 to 31. The result is stored at the
649| location pointed to by 'zPtr'. Argument 'zPtr' points to an array of three
650| 32-bit elements that concatenate in the platform's normal endian order to
651| form a 96-bit integer.
652*----------------------------------------------------------------------------*/
653#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
654INLINE
655void
656 softfloat_shortShiftLeft64To96M(
657 uint64_t a, uint_fast8_t dist, uint32_t *zPtr )
658{
659 zPtr[indexWord( 3, 0 )] = (uint32_t) a<<dist;
660 a >>= 32 - dist;
661 zPtr[indexWord( 3, 2 )] = a>>32;
662 zPtr[indexWord( 3, 1 )] = a;
663}
664#else
665void
666 softfloat_shortShiftLeft64To96M(
667 uint64_t a, uint_fast8_t dist, uint32_t *zPtr );
668#endif
669#endif
670
671#ifndef softfloat_shortShiftLeftM
672/*----------------------------------------------------------------------------
673| Shifts the N-bit unsigned integer pointed to by 'aPtr' left by the number
674| of bits given in 'dist', where N = 'size_words' * 32. The value of 'dist'
675| must be in the range 1 to 31. Any nonzero bits shifted off are lost. The
676| shifted N-bit result is stored at the location pointed to by 'zPtr'. Each
677| of 'aPtr' and 'zPtr' points to a 'size_words'-long array of 32-bit elements
678| that concatenate in the platform's normal endian order to form an N-bit
679| integer.
680*----------------------------------------------------------------------------*/
681void
682 softfloat_shortShiftLeftM(
683 uint_fast8_t size_words,
684 const uint32_t *aPtr,
685 uint_fast8_t dist,
686 uint32_t *zPtr
687 );
688#endif
689
690#ifndef softfloat_shortShiftLeft96M
691/*----------------------------------------------------------------------------
692| This function or macro is the same as 'softfloat_shortShiftLeftM' with
693| 'size_words' = 3 (N = 96).
694*----------------------------------------------------------------------------*/
695#define softfloat_shortShiftLeft96M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 3, aPtr, dist, zPtr )
696#endif
697
698#ifndef softfloat_shortShiftLeft128M
699/*----------------------------------------------------------------------------
700| This function or macro is the same as 'softfloat_shortShiftLeftM' with
701| 'size_words' = 4 (N = 128).
702*----------------------------------------------------------------------------*/
703#define softfloat_shortShiftLeft128M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 4, aPtr, dist, zPtr )
704#endif
705
706#ifndef softfloat_shortShiftLeft160M
707/*----------------------------------------------------------------------------
708| This function or macro is the same as 'softfloat_shortShiftLeftM' with
709| 'size_words' = 5 (N = 160).
710*----------------------------------------------------------------------------*/
711#define softfloat_shortShiftLeft160M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 5, aPtr, dist, zPtr )
712#endif
713
714#ifndef softfloat_shiftLeftM
715/*----------------------------------------------------------------------------
716| Shifts the N-bit unsigned integer pointed to by 'aPtr' left by the number
717| of bits given in 'dist', where N = 'size_words' * 32. The value of 'dist'
718| must not be zero. Any nonzero bits shifted off are lost. The shifted
719| N-bit result is stored at the location pointed to by 'zPtr'. Each of 'aPtr'
720| and 'zPtr' points to a 'size_words'-long array of 32-bit elements that
721| concatenate in the platform's normal endian order to form an N-bit integer.
722| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
723| greater than N, the stored result will be 0.
724*----------------------------------------------------------------------------*/
725void
726 softfloat_shiftLeftM(
727 uint_fast8_t size_words,
728 const uint32_t *aPtr,
729 uint32_t dist,
730 uint32_t *zPtr
731 );
732#endif
733
734#ifndef softfloat_shiftLeft96M
735/*----------------------------------------------------------------------------
736| This function or macro is the same as 'softfloat_shiftLeftM' with
737| 'size_words' = 3 (N = 96).
738*----------------------------------------------------------------------------*/
739#define softfloat_shiftLeft96M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 3, aPtr, dist, zPtr )
740#endif
741
742#ifndef softfloat_shiftLeft128M
743/*----------------------------------------------------------------------------
744| This function or macro is the same as 'softfloat_shiftLeftM' with
745| 'size_words' = 4 (N = 128).
746*----------------------------------------------------------------------------*/
747#define softfloat_shiftLeft128M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 4, aPtr, dist, zPtr )
748#endif
749
750#ifndef softfloat_shiftLeft160M
751/*----------------------------------------------------------------------------
752| This function or macro is the same as 'softfloat_shiftLeftM' with
753| 'size_words' = 5 (N = 160).
754*----------------------------------------------------------------------------*/
755#define softfloat_shiftLeft160M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 5, aPtr, dist, zPtr )
756#endif
757
758#ifndef softfloat_shortShiftRightM
759/*----------------------------------------------------------------------------
760| Shifts the N-bit unsigned integer pointed to by 'aPtr' right by the number
761| of bits given in 'dist', where N = 'size_words' * 32. The value of 'dist'
762| must be in the range 1 to 31. Any nonzero bits shifted off are lost. The
763| shifted N-bit result is stored at the location pointed to by 'zPtr'. Each
764| of 'aPtr' and 'zPtr' points to a 'size_words'-long array of 32-bit elements
765| that concatenate in the platform's normal endian order to form an N-bit
766| integer.
767*----------------------------------------------------------------------------*/
768void
769 softfloat_shortShiftRightM(
770 uint_fast8_t size_words,
771 const uint32_t *aPtr,
772 uint_fast8_t dist,
773 uint32_t *zPtr
774 );
775#endif
776
777#ifndef softfloat_shortShiftRight128M
778/*----------------------------------------------------------------------------
779| This function or macro is the same as 'softfloat_shortShiftRightM' with
780| 'size_words' = 4 (N = 128).
781*----------------------------------------------------------------------------*/
782#define softfloat_shortShiftRight128M( aPtr, dist, zPtr ) softfloat_shortShiftRightM( 4, aPtr, dist, zPtr )
783#endif
784
785#ifndef softfloat_shortShiftRight160M
786/*----------------------------------------------------------------------------
787| This function or macro is the same as 'softfloat_shortShiftRightM' with
788| 'size_words' = 5 (N = 160).
789*----------------------------------------------------------------------------*/
790#define softfloat_shortShiftRight160M( aPtr, dist, zPtr ) softfloat_shortShiftRightM( 5, aPtr, dist, zPtr )
791#endif
792
793#ifndef softfloat_shortShiftRightJamM
794/*----------------------------------------------------------------------------
795| Shifts the N-bit unsigned integer pointed to by 'aPtr' right by the number
796| of bits given in 'dist', where N = 'size_words' * 32. The value of 'dist'
797| must be in the range 1 to 31. If any nonzero bits are shifted off, they are
798| "jammed" into the least-significant bit of the shifted value by setting the
799| least-significant bit to 1. This shifted-and-jammed N-bit result is stored
800| at the location pointed to by 'zPtr'. Each of 'aPtr' and 'zPtr' points
801| to a 'size_words'-long array of 32-bit elements that concatenate in the
802| platform's normal endian order to form an N-bit integer.
803*----------------------------------------------------------------------------*/
804void
805 softfloat_shortShiftRightJamM(
806 uint_fast8_t, const uint32_t *, uint_fast8_t, uint32_t * );
807#endif
808
809#ifndef softfloat_shortShiftRightJam160M
810/*----------------------------------------------------------------------------
811| This function or macro is the same as 'softfloat_shortShiftRightJamM' with
812| 'size_words' = 5 (N = 160).
813*----------------------------------------------------------------------------*/
814#define softfloat_shortShiftRightJam160M( aPtr, dist, zPtr ) softfloat_shortShiftRightJamM( 5, aPtr, dist, zPtr )
815#endif
816
817#ifndef softfloat_shiftRightM
818/*----------------------------------------------------------------------------
819| Shifts the N-bit unsigned integer pointed to by 'aPtr' right by the number
820| of bits given in 'dist', where N = 'size_words' * 32. The value of 'dist'
821| must not be zero. Any nonzero bits shifted off are lost. The shifted
822| N-bit result is stored at the location pointed to by 'zPtr'. Each of 'aPtr'
823| and 'zPtr' points to a 'size_words'-long array of 32-bit elements that
824| concatenate in the platform's normal endian order to form an N-bit integer.
825| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
826| greater than N, the stored result will be 0.
827*----------------------------------------------------------------------------*/
828void
829 softfloat_shiftRightM(
830 uint_fast8_t size_words,
831 const uint32_t *aPtr,
832 uint32_t dist,
833 uint32_t *zPtr
834 );
835#endif
836
837#ifndef softfloat_shiftRight96M
838/*----------------------------------------------------------------------------
839| This function or macro is the same as 'softfloat_shiftRightM' with
840| 'size_words' = 3 (N = 96).
841*----------------------------------------------------------------------------*/
842#define softfloat_shiftRight96M( aPtr, dist, zPtr ) softfloat_shiftRightM( 3, aPtr, dist, zPtr )
843#endif
844
845#ifndef softfloat_shiftRightJamM
846/*----------------------------------------------------------------------------
847| Shifts the N-bit unsigned integer pointed to by 'aPtr' right by the number
848| of bits given in 'dist', where N = 'size_words' * 32. The value of 'dist'
849| must not be zero. If any nonzero bits are shifted off, they are "jammed"
850| into the least-significant bit of the shifted value by setting the least-
851| significant bit to 1. This shifted-and-jammed N-bit result is stored
852| at the location pointed to by 'zPtr'. Each of 'aPtr' and 'zPtr' points
853| to a 'size_words'-long array of 32-bit elements that concatenate in the
854| platform's normal endian order to form an N-bit integer.
855| The value of 'dist' can be arbitrarily large. In particular, if 'dist'
856| is greater than N, the stored result will be either 0 or 1, depending on
857| whether the original N bits are all zeros.
858*----------------------------------------------------------------------------*/
859void
860 softfloat_shiftRightJamM(
861 uint_fast8_t size_words,
862 const uint32_t *aPtr,
863 uint32_t dist,
864 uint32_t *zPtr
865 );
866#endif
867
868#ifndef softfloat_shiftRightJam96M
869/*----------------------------------------------------------------------------
870| This function or macro is the same as 'softfloat_shiftRightJamM' with
871| 'size_words' = 3 (N = 96).
872*----------------------------------------------------------------------------*/
873#define softfloat_shiftRightJam96M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 3, aPtr, dist, zPtr )
874#endif
875
876#ifndef softfloat_shiftRightJam128M
877/*----------------------------------------------------------------------------
878| This function or macro is the same as 'softfloat_shiftRightJamM' with
879| 'size_words' = 4 (N = 128).
880*----------------------------------------------------------------------------*/
881#define softfloat_shiftRightJam128M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 4, aPtr, dist, zPtr )
882#endif
883
884#ifndef softfloat_shiftRightJam160M
885/*----------------------------------------------------------------------------
886| This function or macro is the same as 'softfloat_shiftRightJamM' with
887| 'size_words' = 5 (N = 160).
888*----------------------------------------------------------------------------*/
889#define softfloat_shiftRightJam160M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 5, aPtr, dist, zPtr )
890#endif
891
892#ifndef softfloat_addM
893/*----------------------------------------------------------------------------
894| Adds the two N-bit integers pointed to by 'aPtr' and 'bPtr', where N =
895| 'size_words' * 32. The addition is modulo 2^N, so any carry out is lost.
896| The N-bit sum is stored at the location pointed to by 'zPtr'. Each of
897| 'aPtr', 'bPtr', and 'zPtr' points to a 'size_words'-long array of 32-bit
898| elements that concatenate in the platform's normal endian order to form an
899| N-bit integer.
900*----------------------------------------------------------------------------*/
901void
902 softfloat_addM(
903 uint_fast8_t size_words,
904 const uint32_t *aPtr,
905 const uint32_t *bPtr,
906 uint32_t *zPtr
907 );
908#endif
909
910#ifndef softfloat_add96M
911/*----------------------------------------------------------------------------
912| This function or macro is the same as 'softfloat_addM' with 'size_words'
913| = 3 (N = 96).
914*----------------------------------------------------------------------------*/
915#define softfloat_add96M( aPtr, bPtr, zPtr ) softfloat_addM( 3, aPtr, bPtr, zPtr )
916#endif
917
918#ifndef softfloat_add128M
919/*----------------------------------------------------------------------------
920| This function or macro is the same as 'softfloat_addM' with 'size_words'
921| = 4 (N = 128).
922*----------------------------------------------------------------------------*/
923#define softfloat_add128M( aPtr, bPtr, zPtr ) softfloat_addM( 4, aPtr, bPtr, zPtr )
924#endif
925
926#ifndef softfloat_add160M
927/*----------------------------------------------------------------------------
928| This function or macro is the same as 'softfloat_addM' with 'size_words'
929| = 5 (N = 160).
930*----------------------------------------------------------------------------*/
931#define softfloat_add160M( aPtr, bPtr, zPtr ) softfloat_addM( 5, aPtr, bPtr, zPtr )
932#endif
933
934#ifndef softfloat_addCarryM
935/*----------------------------------------------------------------------------
936| Adds the two N-bit unsigned integers pointed to by 'aPtr' and 'bPtr', where
937| N = 'size_words' * 32, plus 'carry', which must be either 0 or 1. The N-bit
938| sum (modulo 2^N) is stored at the location pointed to by 'zPtr', and any
939| carry out is returned as the result. Each of 'aPtr', 'bPtr', and 'zPtr'
940| points to a 'size_words'-long array of 32-bit elements that concatenate in
941| the platform's normal endian order to form an N-bit integer.
942*----------------------------------------------------------------------------*/
943uint_fast8_t
944 softfloat_addCarryM(
945 uint_fast8_t size_words,
946 const uint32_t *aPtr,
947 const uint32_t *bPtr,
948 uint_fast8_t carry,
949 uint32_t *zPtr
950 );
951#endif
952
953#ifndef softfloat_addComplCarryM
954/*----------------------------------------------------------------------------
955| This function or macro is the same as 'softfloat_addCarryM', except that
956| the value of the unsigned integer pointed to by 'bPtr' is bit-wise completed
957| before the addition.
958*----------------------------------------------------------------------------*/
959uint_fast8_t
960 softfloat_addComplCarryM(
961 uint_fast8_t size_words,
962 const uint32_t *aPtr,
963 const uint32_t *bPtr,
964 uint_fast8_t carry,
965 uint32_t *zPtr
966 );
967#endif
968
969#ifndef softfloat_addComplCarry96M
970/*----------------------------------------------------------------------------
971| This function or macro is the same as 'softfloat_addComplCarryM' with
972| 'size_words' = 3 (N = 96).
973*----------------------------------------------------------------------------*/
974#define softfloat_addComplCarry96M( aPtr, bPtr, carry, zPtr ) softfloat_addComplCarryM( 3, aPtr, bPtr, carry, zPtr )
975#endif
976
977#ifndef softfloat_negXM
978/*----------------------------------------------------------------------------
979| Replaces the N-bit unsigned integer pointed to by 'zPtr' by the
980| 2s-complement of itself, where N = 'size_words' * 32. Argument 'zPtr'
981| points to a 'size_words'-long array of 32-bit elements that concatenate in
982| the platform's normal endian order to form an N-bit integer.
983*----------------------------------------------------------------------------*/
984void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr );
985#endif
986
987#ifndef softfloat_negX96M
988/*----------------------------------------------------------------------------
989| This function or macro is the same as 'softfloat_negXM' with 'size_words'
990| = 3 (N = 96).
991*----------------------------------------------------------------------------*/
992#define softfloat_negX96M( zPtr ) softfloat_negXM( 3, zPtr )
993#endif
994
995#ifndef softfloat_negX128M
996/*----------------------------------------------------------------------------
997| This function or macro is the same as 'softfloat_negXM' with 'size_words'
998| = 4 (N = 128).
999*----------------------------------------------------------------------------*/
1000#define softfloat_negX128M( zPtr ) softfloat_negXM( 4, zPtr )
1001#endif
1002
1003#ifndef softfloat_negX160M
1004/*----------------------------------------------------------------------------
1005| This function or macro is the same as 'softfloat_negXM' with 'size_words'
1006| = 5 (N = 160).
1007*----------------------------------------------------------------------------*/
1008#define softfloat_negX160M( zPtr ) softfloat_negXM( 5, zPtr )
1009#endif
1010
1011#ifndef softfloat_negX256M
1012/*----------------------------------------------------------------------------
1013| This function or macro is the same as 'softfloat_negXM' with 'size_words'
1014| = 8 (N = 256).
1015*----------------------------------------------------------------------------*/
1016#define softfloat_negX256M( zPtr ) softfloat_negXM( 8, zPtr )
1017#endif
1018
1019#ifndef softfloat_sub1XM
1020/*----------------------------------------------------------------------------
1021| Subtracts 1 from the N-bit integer pointed to by 'zPtr', where N =
1022| 'size_words' * 32. The subtraction is modulo 2^N, so any borrow out (carry
1023| out) is lost. Argument 'zPtr' points to a 'size_words'-long array of 32-bit
1024| elements that concatenate in the platform's normal endian order to form an
1025| N-bit integer.
1026*----------------------------------------------------------------------------*/
1027void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr );
1028#endif
1029
1030#ifndef softfloat_sub1X96M
1031/*----------------------------------------------------------------------------
1032| This function or macro is the same as 'softfloat_sub1XM' with 'size_words'
1033| = 3 (N = 96).
1034*----------------------------------------------------------------------------*/
1035#define softfloat_sub1X96M( zPtr ) softfloat_sub1XM( 3, zPtr )
1036#endif
1037
1038#ifndef softfloat_sub1X160M
1039/*----------------------------------------------------------------------------
1040| This function or macro is the same as 'softfloat_sub1XM' with 'size_words'
1041| = 5 (N = 160).
1042*----------------------------------------------------------------------------*/
1043#define softfloat_sub1X160M( zPtr ) softfloat_sub1XM( 5, zPtr )
1044#endif
1045
1046#ifndef softfloat_subM
1047/*----------------------------------------------------------------------------
1048| Subtracts the two N-bit integers pointed to by 'aPtr' and 'bPtr', where N =
1049| 'size_words' * 32. The subtraction is modulo 2^N, so any borrow out (carry
1050| out) is lost. The N-bit difference is stored at the location pointed to by
1051| 'zPtr'. Each of 'aPtr', 'bPtr', and 'zPtr' points to a 'size_words'-long
1052| array of 32-bit elements that concatenate in the platform's normal endian
1053| order to form an N-bit integer.
1054*----------------------------------------------------------------------------*/
1055void
1056 softfloat_subM(
1057 uint_fast8_t size_words,
1058 const uint32_t *aPtr,
1059 const uint32_t *bPtr,
1060 uint32_t *zPtr
1061 );
1062#endif
1063
1064#ifndef softfloat_sub96M
1065/*----------------------------------------------------------------------------
1066| This function or macro is the same as 'softfloat_subM' with 'size_words'
1067| = 3 (N = 96).
1068*----------------------------------------------------------------------------*/
1069#define softfloat_sub96M( aPtr, bPtr, zPtr ) softfloat_subM( 3, aPtr, bPtr, zPtr )
1070#endif
1071
1072#ifndef softfloat_sub128M
1073/*----------------------------------------------------------------------------
1074| This function or macro is the same as 'softfloat_subM' with 'size_words'
1075| = 4 (N = 128).
1076*----------------------------------------------------------------------------*/
1077#define softfloat_sub128M( aPtr, bPtr, zPtr ) softfloat_subM( 4, aPtr, bPtr, zPtr )
1078#endif
1079
1080#ifndef softfloat_sub160M
1081/*----------------------------------------------------------------------------
1082| This function or macro is the same as 'softfloat_subM' with 'size_words'
1083| = 5 (N = 160).
1084*----------------------------------------------------------------------------*/
1085#define softfloat_sub160M( aPtr, bPtr, zPtr ) softfloat_subM( 5, aPtr, bPtr, zPtr )
1086#endif
1087
1088#ifndef softfloat_mul64To128M
1089/*----------------------------------------------------------------------------
1090| Multiplies 'a' and 'b' and stores the 128-bit product at the location
1091| pointed to by 'zPtr'. Argument 'zPtr' points to an array of four 32-bit
1092| elements that concatenate in the platform's normal endian order to form a
1093| 128-bit integer.
1094*----------------------------------------------------------------------------*/
1095void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr );
1096#endif
1097
1098#ifndef softfloat_mul128MTo256M
1099/*----------------------------------------------------------------------------
1100| Multiplies the two 128-bit unsigned integers pointed to by 'aPtr' and
1101| 'bPtr', and stores the 256-bit product at the location pointed to by 'zPtr'.
1102| Each of 'aPtr' and 'bPtr' points to an array of four 32-bit elements that
1103| concatenate in the platform's normal endian order to form a 128-bit integer.
1104| Argument 'zPtr' points to an array of eight 32-bit elements that concatenate
1105| to form a 256-bit integer.
1106*----------------------------------------------------------------------------*/
1107void
1108 softfloat_mul128MTo256M(
1109 const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr );
1110#endif
1111
1112#ifndef softfloat_remStepMBy32
1113/*----------------------------------------------------------------------------
1114| Performs a "remainder reduction step" as follows: Arguments 'remPtr' and
1115| 'bPtr' both point to N-bit unsigned integers, where N = 'size_words' * 32.
1116| Defining R and B as the values of those integers, the expression (R<<'dist')
1117| - B * q is computed modulo 2^N, and the N-bit result is stored at the
1118| location pointed to by 'zPtr'. Each of 'remPtr', 'bPtr', and 'zPtr' points
1119| to a 'size_words'-long array of 32-bit elements that concatenate in the
1120| platform's normal endian order to form an N-bit integer.
1121*----------------------------------------------------------------------------*/
1122void
1123 softfloat_remStepMBy32(
1124 uint_fast8_t size_words,
1125 const uint32_t *remPtr,
1126 uint_fast8_t dist,
1127 const uint32_t *bPtr,
1128 uint32_t q,
1129 uint32_t *zPtr
1130 );
1131#endif
1132
1133#ifndef softfloat_remStep96MBy32
1134/*----------------------------------------------------------------------------
1135| This function or macro is the same as 'softfloat_remStepMBy32' with
1136| 'size_words' = 3 (N = 96).
1137*----------------------------------------------------------------------------*/
1138#define softfloat_remStep96MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 3, remPtr, dist, bPtr, q, zPtr )
1139#endif
1140
1141#ifndef softfloat_remStep128MBy32
1142/*----------------------------------------------------------------------------
1143| This function or macro is the same as 'softfloat_remStepMBy32' with
1144| 'size_words' = 4 (N = 128).
1145*----------------------------------------------------------------------------*/
1146#define softfloat_remStep128MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 4, remPtr, dist, bPtr, q, zPtr )
1147#endif
1148
1149#ifndef softfloat_remStep160MBy32
1150/*----------------------------------------------------------------------------
1151| This function or macro is the same as 'softfloat_remStepMBy32' with
1152| 'size_words' = 5 (N = 160).
1153*----------------------------------------------------------------------------*/
1154#define softfloat_remStep160MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 5, remPtr, dist, bPtr, q, zPtr )
1155#endif
1156
1157#endif
1158
1159#endif
1160
deps/SoftFloat-3e/source/include/softfloat.h deleted-372
...@@ -1,372 +0,0 @@
1
2/*============================================================================
3
4This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37
38/*============================================================================
39| Note: If SoftFloat is made available as a general library for programs to
40| use, it is strongly recommended that a platform-specific version of this
41| header, "softfloat.h", be created that folds in "softfloat_types.h" and that
42| eliminates all dependencies on compile-time macros.
43*============================================================================*/
44
45
46#ifndef softfloat_h
47#define softfloat_h 1
48
49#include <stdbool.h>
50#include <stdint.h>
51#include "softfloat_types.h"
52
53#ifndef THREAD_LOCAL
54#define THREAD_LOCAL
55#endif
56
57/*----------------------------------------------------------------------------
58| Software floating-point underflow tininess-detection mode.
59*----------------------------------------------------------------------------*/
60extern THREAD_LOCAL uint_fast8_t softfloat_detectTininess;
61enum {
62 softfloat_tininess_beforeRounding = 0,
63 softfloat_tininess_afterRounding = 1
64};
65
66/*----------------------------------------------------------------------------
67| Software floating-point rounding mode. (Mode "odd" is supported only if
68| SoftFloat is compiled with macro 'SOFTFLOAT_ROUND_ODD' defined.)
69*----------------------------------------------------------------------------*/
70extern THREAD_LOCAL uint_fast8_t softfloat_roundingMode;
71enum {
72 softfloat_round_near_even = 0,
73 softfloat_round_minMag = 1,
74 softfloat_round_min = 2,
75 softfloat_round_max = 3,
76 softfloat_round_near_maxMag = 4,
77 softfloat_round_odd = 6
78};
79
80/*----------------------------------------------------------------------------
81| Software floating-point exception flags.
82*----------------------------------------------------------------------------*/
83extern THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags;
84enum {
85 softfloat_flag_inexact = 1,
86 softfloat_flag_underflow = 2,
87 softfloat_flag_overflow = 4,
88 softfloat_flag_infinite = 8,
89 softfloat_flag_invalid = 16
90};
91
92/*----------------------------------------------------------------------------
93| Routine to raise any or all of the software floating-point exception flags.
94*----------------------------------------------------------------------------*/
95void softfloat_raiseFlags( uint_fast8_t );
96
97/*----------------------------------------------------------------------------
98| Integer-to-floating-point conversion routines.
99*----------------------------------------------------------------------------*/
100float16_t ui32_to_f16( uint32_t );
101float32_t ui32_to_f32( uint32_t );
102float64_t ui32_to_f64( uint32_t );
103#ifdef SOFTFLOAT_FAST_INT64
104extFloat80_t ui32_to_extF80( uint32_t );
105float128_t ui32_to_f128( uint32_t );
106#endif
107void ui32_to_extF80M( uint32_t, extFloat80_t * );
108void ui32_to_f128M( uint32_t, float128_t * );
109float16_t ui64_to_f16( uint64_t );
110float32_t ui64_to_f32( uint64_t );
111float64_t ui64_to_f64( uint64_t );
112#ifdef SOFTFLOAT_FAST_INT64
113extFloat80_t ui64_to_extF80( uint64_t );
114float128_t ui64_to_f128( uint64_t );
115#endif
116void ui64_to_extF80M( uint64_t, extFloat80_t * );
117void ui64_to_f128M( uint64_t, float128_t * );
118float16_t i32_to_f16( int32_t );
119float32_t i32_to_f32( int32_t );
120float64_t i32_to_f64( int32_t );
121#ifdef SOFTFLOAT_FAST_INT64
122extFloat80_t i32_to_extF80( int32_t );
123float128_t i32_to_f128( int32_t );
124#endif
125void i32_to_extF80M( int32_t, extFloat80_t * );
126void i32_to_f128M( int32_t, float128_t * );
127float16_t i64_to_f16( int64_t );
128float32_t i64_to_f32( int64_t );
129float64_t i64_to_f64( int64_t );
130#ifdef SOFTFLOAT_FAST_INT64
131extFloat80_t i64_to_extF80( int64_t );
132float128_t i64_to_f128( int64_t );
133#endif
134void i64_to_extF80M( int64_t, extFloat80_t * );
135void i64_to_f128M( int64_t, float128_t * );
136
137/*----------------------------------------------------------------------------
138| 16-bit (half-precision) floating-point operations.
139*----------------------------------------------------------------------------*/
140uint_fast32_t f16_to_ui32( float16_t, uint_fast8_t, bool );
141uint_fast64_t f16_to_ui64( float16_t, uint_fast8_t, bool );
142int_fast32_t f16_to_i32( float16_t, uint_fast8_t, bool );
143int_fast64_t f16_to_i64( float16_t, uint_fast8_t, bool );
144uint_fast32_t f16_to_ui32_r_minMag( float16_t, bool );
145uint_fast64_t f16_to_ui64_r_minMag( float16_t, bool );
146int_fast32_t f16_to_i32_r_minMag( float16_t, bool );
147int_fast64_t f16_to_i64_r_minMag( float16_t, bool );
148float32_t f16_to_f32( float16_t );
149float64_t f16_to_f64( float16_t );
150#ifdef SOFTFLOAT_FAST_INT64
151extFloat80_t f16_to_extF80( float16_t );
152float128_t f16_to_f128( float16_t );
153#endif
154void f16_to_extF80M( float16_t, extFloat80_t * );
155void f16_to_f128M( float16_t, float128_t * );
156float16_t f16_roundToInt( float16_t, uint_fast8_t, bool );
157float16_t f16_add( float16_t, float16_t );
158float16_t f16_sub( float16_t, float16_t );
159float16_t f16_mul( float16_t, float16_t );
160float16_t f16_mulAdd( float16_t, float16_t, float16_t );
161float16_t f16_div( float16_t, float16_t );
162float16_t f16_rem( float16_t, float16_t );
163float16_t f16_sqrt( float16_t );
164bool f16_eq( float16_t, float16_t );
165bool f16_le( float16_t, float16_t );
166bool f16_lt( float16_t, float16_t );
167bool f16_eq_signaling( float16_t, float16_t );
168bool f16_le_quiet( float16_t, float16_t );
169bool f16_lt_quiet( float16_t, float16_t );
170bool f16_isSignalingNaN( float16_t );
171
172/*----------------------------------------------------------------------------
173| 32-bit (single-precision) floating-point operations.
174*----------------------------------------------------------------------------*/
175uint_fast32_t f32_to_ui32( float32_t, uint_fast8_t, bool );
176uint_fast64_t f32_to_ui64( float32_t, uint_fast8_t, bool );
177int_fast32_t f32_to_i32( float32_t, uint_fast8_t, bool );
178int_fast64_t f32_to_i64( float32_t, uint_fast8_t, bool );
179uint_fast32_t f32_to_ui32_r_minMag( float32_t, bool );
180uint_fast64_t f32_to_ui64_r_minMag( float32_t, bool );
181int_fast32_t f32_to_i32_r_minMag( float32_t, bool );
182int_fast64_t f32_to_i64_r_minMag( float32_t, bool );
183float16_t f32_to_f16( float32_t );
184float64_t f32_to_f64( float32_t );
185#ifdef SOFTFLOAT_FAST_INT64
186extFloat80_t f32_to_extF80( float32_t );
187float128_t f32_to_f128( float32_t );
188#endif
189void f32_to_extF80M( float32_t, extFloat80_t * );
190void f32_to_f128M( float32_t, float128_t * );
191float32_t f32_roundToInt( float32_t, uint_fast8_t, bool );
192float32_t f32_add( float32_t, float32_t );
193float32_t f32_sub( float32_t, float32_t );
194float32_t f32_mul( float32_t, float32_t );
195float32_t f32_mulAdd( float32_t, float32_t, float32_t );
196float32_t f32_div( float32_t, float32_t );
197float32_t f32_rem( float32_t, float32_t );
198float32_t f32_sqrt( float32_t );
199bool f32_eq( float32_t, float32_t );
200bool f32_le( float32_t, float32_t );
201bool f32_lt( float32_t, float32_t );
202bool f32_eq_signaling( float32_t, float32_t );
203bool f32_le_quiet( float32_t, float32_t );
204bool f32_lt_quiet( float32_t, float32_t );
205bool f32_isSignalingNaN( float32_t );
206
207/*----------------------------------------------------------------------------
208| 64-bit (double-precision) floating-point operations.
209*----------------------------------------------------------------------------*/
210uint_fast32_t f64_to_ui32( float64_t, uint_fast8_t, bool );
211uint_fast64_t f64_to_ui64( float64_t, uint_fast8_t, bool );
212int_fast32_t f64_to_i32( float64_t, uint_fast8_t, bool );
213int_fast64_t f64_to_i64( float64_t, uint_fast8_t, bool );
214uint_fast32_t f64_to_ui32_r_minMag( float64_t, bool );
215uint_fast64_t f64_to_ui64_r_minMag( float64_t, bool );
216int_fast32_t f64_to_i32_r_minMag( float64_t, bool );
217int_fast64_t f64_to_i64_r_minMag( float64_t, bool );
218float16_t f64_to_f16( float64_t );
219float32_t f64_to_f32( float64_t );
220#ifdef SOFTFLOAT_FAST_INT64
221extFloat80_t f64_to_extF80( float64_t );
222float128_t f64_to_f128( float64_t );
223#endif
224void f64_to_extF80M( float64_t, extFloat80_t * );
225void f64_to_f128M( float64_t, float128_t * );
226float64_t f64_roundToInt( float64_t, uint_fast8_t, bool );
227float64_t f64_add( float64_t, float64_t );
228float64_t f64_sub( float64_t, float64_t );
229float64_t f64_mul( float64_t, float64_t );
230float64_t f64_mulAdd( float64_t, float64_t, float64_t );
231float64_t f64_div( float64_t, float64_t );
232float64_t f64_rem( float64_t, float64_t );
233float64_t f64_sqrt( float64_t );
234bool f64_eq( float64_t, float64_t );
235bool f64_le( float64_t, float64_t );
236bool f64_lt( float64_t, float64_t );
237bool f64_eq_signaling( float64_t, float64_t );
238bool f64_le_quiet( float64_t, float64_t );
239bool f64_lt_quiet( float64_t, float64_t );
240bool f64_isSignalingNaN( float64_t );
241
242/*----------------------------------------------------------------------------
243| Rounding precision for 80-bit extended double-precision floating-point.
244| Valid values are 32, 64, and 80.
245*----------------------------------------------------------------------------*/
246extern THREAD_LOCAL uint_fast8_t extF80_roundingPrecision;
247
248/*----------------------------------------------------------------------------
249| 80-bit extended double-precision floating-point operations.
250*----------------------------------------------------------------------------*/
251#ifdef SOFTFLOAT_FAST_INT64
252uint_fast32_t extF80_to_ui32( extFloat80_t, uint_fast8_t, bool );
253uint_fast64_t extF80_to_ui64( extFloat80_t, uint_fast8_t, bool );
254int_fast32_t extF80_to_i32( extFloat80_t, uint_fast8_t, bool );
255int_fast64_t extF80_to_i64( extFloat80_t, uint_fast8_t, bool );
256uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t, bool );
257uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t, bool );
258int_fast32_t extF80_to_i32_r_minMag( extFloat80_t, bool );
259int_fast64_t extF80_to_i64_r_minMag( extFloat80_t, bool );
260float16_t extF80_to_f16( extFloat80_t );
261float32_t extF80_to_f32( extFloat80_t );
262float64_t extF80_to_f64( extFloat80_t );
263float128_t extF80_to_f128( extFloat80_t );
264extFloat80_t extF80_roundToInt( extFloat80_t, uint_fast8_t, bool );
265extFloat80_t extF80_add( extFloat80_t, extFloat80_t );
266extFloat80_t extF80_sub( extFloat80_t, extFloat80_t );
267extFloat80_t extF80_mul( extFloat80_t, extFloat80_t );
268extFloat80_t extF80_div( extFloat80_t, extFloat80_t );
269extFloat80_t extF80_rem( extFloat80_t, extFloat80_t );
270extFloat80_t extF80_sqrt( extFloat80_t );
271bool extF80_eq( extFloat80_t, extFloat80_t );
272bool extF80_le( extFloat80_t, extFloat80_t );
273bool extF80_lt( extFloat80_t, extFloat80_t );
274bool extF80_eq_signaling( extFloat80_t, extFloat80_t );
275bool extF80_le_quiet( extFloat80_t, extFloat80_t );
276bool extF80_lt_quiet( extFloat80_t, extFloat80_t );
277bool extF80_isSignalingNaN( extFloat80_t );
278#endif
279uint_fast32_t extF80M_to_ui32( const extFloat80_t *, uint_fast8_t, bool );
280uint_fast64_t extF80M_to_ui64( const extFloat80_t *, uint_fast8_t, bool );
281int_fast32_t extF80M_to_i32( const extFloat80_t *, uint_fast8_t, bool );
282int_fast64_t extF80M_to_i64( const extFloat80_t *, uint_fast8_t, bool );
283uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *, bool );
284uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *, bool );
285int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *, bool );
286int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *, bool );
287float16_t extF80M_to_f16( const extFloat80_t * );
288float32_t extF80M_to_f32( const extFloat80_t * );
289float64_t extF80M_to_f64( const extFloat80_t * );
290void extF80M_to_f128M( const extFloat80_t *, float128_t * );
291void
292 extF80M_roundToInt(
293 const extFloat80_t *, uint_fast8_t, bool, extFloat80_t * );
294void extF80M_add( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
295void extF80M_sub( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
296void extF80M_mul( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
297void extF80M_div( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
298void extF80M_rem( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
299void extF80M_sqrt( const extFloat80_t *, extFloat80_t * );
300bool extF80M_eq( const extFloat80_t *, const extFloat80_t * );
301bool extF80M_le( const extFloat80_t *, const extFloat80_t * );
302bool extF80M_lt( const extFloat80_t *, const extFloat80_t * );
303bool extF80M_eq_signaling( const extFloat80_t *, const extFloat80_t * );
304bool extF80M_le_quiet( const extFloat80_t *, const extFloat80_t * );
305bool extF80M_lt_quiet( const extFloat80_t *, const extFloat80_t * );
306bool extF80M_isSignalingNaN( const extFloat80_t * );
307
308/*----------------------------------------------------------------------------
309| 128-bit (quadruple-precision) floating-point operations.
310*----------------------------------------------------------------------------*/
311#ifdef SOFTFLOAT_FAST_INT64
312uint_fast32_t f128_to_ui32( float128_t, uint_fast8_t, bool );
313uint_fast64_t f128_to_ui64( float128_t, uint_fast8_t, bool );
314int_fast32_t f128_to_i32( float128_t, uint_fast8_t, bool );
315int_fast64_t f128_to_i64( float128_t, uint_fast8_t, bool );
316uint_fast32_t f128_to_ui32_r_minMag( float128_t, bool );
317uint_fast64_t f128_to_ui64_r_minMag( float128_t, bool );
318int_fast32_t f128_to_i32_r_minMag( float128_t, bool );
319int_fast64_t f128_to_i64_r_minMag( float128_t, bool );
320float16_t f128_to_f16( float128_t );
321float32_t f128_to_f32( float128_t );
322float64_t f128_to_f64( float128_t );
323extFloat80_t f128_to_extF80( float128_t );
324float128_t f128_roundToInt( float128_t, uint_fast8_t, bool );
325float128_t f128_add( float128_t, float128_t );
326float128_t f128_sub( float128_t, float128_t );
327float128_t f128_mul( float128_t, float128_t );
328float128_t f128_mulAdd( float128_t, float128_t, float128_t );
329float128_t f128_div( float128_t, float128_t );
330float128_t f128_rem( float128_t, float128_t );
331float128_t f128_sqrt( float128_t );
332bool f128_eq( float128_t, float128_t );
333bool f128_le( float128_t, float128_t );
334bool f128_lt( float128_t, float128_t );
335bool f128_eq_signaling( float128_t, float128_t );
336bool f128_le_quiet( float128_t, float128_t );
337bool f128_lt_quiet( float128_t, float128_t );
338bool f128_isSignalingNaN( float128_t );
339#endif
340uint_fast32_t f128M_to_ui32( const float128_t *, uint_fast8_t, bool );
341uint_fast64_t f128M_to_ui64( const float128_t *, uint_fast8_t, bool );
342int_fast32_t f128M_to_i32( const float128_t *, uint_fast8_t, bool );
343int_fast64_t f128M_to_i64( const float128_t *, uint_fast8_t, bool );
344uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *, bool );
345uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *, bool );
346int_fast32_t f128M_to_i32_r_minMag( const float128_t *, bool );
347int_fast64_t f128M_to_i64_r_minMag( const float128_t *, bool );
348float16_t f128M_to_f16( const float128_t * );
349float32_t f128M_to_f32( const float128_t * );
350float64_t f128M_to_f64( const float128_t * );
351void f128M_to_extF80M( const float128_t *, extFloat80_t * );
352void f128M_roundToInt( const float128_t *, uint_fast8_t, bool, float128_t * );
353void f128M_add( const float128_t *, const float128_t *, float128_t * );
354void f128M_sub( const float128_t *, const float128_t *, float128_t * );
355void f128M_mul( const float128_t *, const float128_t *, float128_t * );
356void
357 f128M_mulAdd(
358 const float128_t *, const float128_t *, const float128_t *, float128_t *
359 );
360void f128M_div( const float128_t *, const float128_t *, float128_t * );
361void f128M_rem( const float128_t *, const float128_t *, float128_t * );
362void f128M_sqrt( const float128_t *, float128_t * );
363bool f128M_eq( const float128_t *, const float128_t * );
364bool f128M_le( const float128_t *, const float128_t * );
365bool f128M_lt( const float128_t *, const float128_t * );
366bool f128M_eq_signaling( const float128_t *, const float128_t * );
367bool f128M_le_quiet( const float128_t *, const float128_t * );
368bool f128M_lt_quiet( const float128_t *, const float128_t * );
369bool f128M_isSignalingNaN( const float128_t * );
370
371#endif
372
deps/SoftFloat-3e/source/include/softfloat_types.h deleted-82
...@@ -1,82 +0,0 @@
1
2/*============================================================================
3
4This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#ifndef softfloat_types_h
38#define softfloat_types_h 1
39
40#include "platform.h"
41#include <stdint.h>
42
43/*----------------------------------------------------------------------------
44| Types used to pass 16-bit, 32-bit, 64-bit, and 128-bit floating-point
45| arguments and results to/from functions. These types must be exactly
46| 16 bits, 32 bits, 64 bits, and 128 bits in size, respectively. Where a
47| platform has "native" support for IEEE-Standard floating-point formats,
48| the types below may, if desired, be defined as aliases for the native types
49| (typically 'float' and 'double', and possibly 'long double').
50*----------------------------------------------------------------------------*/
51typedef struct { uint16_t v; } float16_t;
52typedef struct { uint32_t v; } float32_t;
53typedef struct { uint64_t v; } float64_t;
54typedef struct { uint64_t v[2]; } float128_t;
55
56/*----------------------------------------------------------------------------
57| The format of an 80-bit extended floating-point number in memory. This
58| structure must contain a 16-bit field named 'signExp' and a 64-bit field
59| named 'signif'.
60*----------------------------------------------------------------------------*/
61#ifdef LITTLEENDIAN
62struct extFloat80M { uint64_t signif; uint16_t signExp; };
63#else
64struct extFloat80M { uint16_t signExp; uint64_t signif; };
65#endif
66
67/*----------------------------------------------------------------------------
68| The type used to pass 80-bit extended floating-point arguments and
69| results to/from functions. This type must have size identical to
70| 'struct extFloat80M'. Type 'extFloat80_t' can be defined as an alias for
71| 'struct extFloat80M'. Alternatively, if a platform has "native" support
72| for IEEE-Standard 80-bit extended floating-point, it may be possible,
73| if desired, to define 'extFloat80_t' as an alias for the native type
74| (presumably either 'long double' or a nonstandard compiler-intrinsic type).
75| In that case, the 'signif' and 'signExp' fields of 'struct extFloat80M'
76| must align exactly with the locations in memory of the sign, exponent, and
77| significand of the native type.
78*----------------------------------------------------------------------------*/
79typedef struct extFloat80M extFloat80_t;
80
81#endif
82
deps/SoftFloat-3e/source/s_add128.c deleted-55
...@@ -1,55 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_add128
42
43struct uint128
44 softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
45{
46 struct uint128 z;
47
48 z.v0 = a0 + b0;
49 z.v64 = a64 + b64 + (z.v0 < a0);
50 return z;
51
52}
53
54#endif
55
deps/SoftFloat-3e/source/s_add256M.c deleted-65
...@@ -1,65 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_add256M
42
43void
44 softfloat_add256M(
45 const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr )
46{
47 unsigned int index;
48 uint_fast8_t carry;
49 uint64_t wordA, wordZ;
50
51 index = indexWordLo( 4 );
52 carry = 0;
53 for (;;) {
54 wordA = aPtr[index];
55 wordZ = wordA + bPtr[index] + carry;
56 zPtr[index] = wordZ;
57 if ( index == indexWordHi( 4 ) ) break;
58 if ( wordZ != wordA ) carry = (wordZ < wordA);
59 index += wordIncr;
60 }
61
62}
63
64#endif
65
deps/SoftFloat-3e/source/s_addCarryM.c deleted-70
...@@ -1,70 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_addCarryM
42
43uint_fast8_t
44 softfloat_addCarryM(
45 uint_fast8_t size_words,
46 const uint32_t *aPtr,
47 const uint32_t *bPtr,
48 uint_fast8_t carry,
49 uint32_t *zPtr
50 )
51{
52 unsigned int index, lastIndex;
53 uint32_t wordA, wordZ;
54
55 index = indexWordLo( size_words );
56 lastIndex = indexWordHi( size_words );
57 for (;;) {
58 wordA = aPtr[index];
59 wordZ = wordA + bPtr[index] + carry;
60 zPtr[index] = wordZ;
61 if ( wordZ != wordA ) carry = (wordZ < wordA);
62 if ( index == lastIndex ) break;
63 index += wordIncr;
64 }
65 return carry;
66
67}
68
69#endif
70
deps/SoftFloat-3e/source/s_addComplCarryM.c deleted-70
...@@ -1,70 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_addComplCarryM
42
43uint_fast8_t
44 softfloat_addComplCarryM(
45 uint_fast8_t size_words,
46 const uint32_t *aPtr,
47 const uint32_t *bPtr,
48 uint_fast8_t carry,
49 uint32_t *zPtr
50 )
51{
52 unsigned int index, lastIndex;
53 uint32_t wordA, wordZ;
54
55 index = indexWordLo( size_words );
56 lastIndex = indexWordHi( size_words );
57 for (;;) {
58 wordA = aPtr[index];
59 wordZ = wordA + ~bPtr[index] + carry;
60 zPtr[index] = wordZ;
61 if ( wordZ != wordA ) carry = (wordZ < wordA);
62 if ( index == lastIndex ) break;
63 index += wordIncr;
64 }
65 return carry;
66
67}
68
69#endif
70
deps/SoftFloat-3e/source/s_addExtF80M.c deleted-186
...@@ -1,186 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44void
45 softfloat_addExtF80M(
46 const struct extFloat80M *aSPtr,
47 const struct extFloat80M *bSPtr,
48 struct extFloat80M *zSPtr,
49 bool negateB
50 )
51{
52 uint32_t uiA64;
53 int32_t expA;
54 uint32_t uiB64;
55 int32_t expB;
56 uint32_t uiZ64;
57 bool signZ, signB;
58 const struct extFloat80M *tempSPtr;
59 uint64_t sigZ, sigB;
60 void
61 (*roundPackRoutinePtr)(
62 bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * );
63 int32_t expDiff;
64 uint32_t extSigX[3], sigZExtra;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 uiA64 = aSPtr->signExp;
69 expA = expExtF80UI64( uiA64 );
70 uiB64 = bSPtr->signExp;
71 expB = expExtF80UI64( uiB64 );
72 /*------------------------------------------------------------------------
73 *------------------------------------------------------------------------*/
74 if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
75 if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return;
76 uiZ64 = uiA64;
77 if ( expB == 0x7FFF ) {
78 uiZ64 = uiB64 ^ packToExtF80UI64( negateB, 0 );
79 if ( (expA == 0x7FFF) && (uiZ64 != uiA64) ) {
80 softfloat_invalidExtF80M( zSPtr );
81 return;
82 }
83 }
84 zSPtr->signExp = uiZ64;
85 zSPtr->signif = UINT64_C( 0x8000000000000000 );
86 return;
87 }
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 signZ = signExtF80UI64( uiA64 );
91 signB = signExtF80UI64( uiB64 ) ^ negateB;
92 negateB = (signZ != signB);
93 if ( expA < expB ) {
94 signZ = signB;
95 expA = expB;
96 expB = expExtF80UI64( uiA64 );
97 tempSPtr = aSPtr;
98 aSPtr = bSPtr;
99 bSPtr = tempSPtr;
100 }
101 if ( ! expB ) {
102 expB = 1;
103 if ( ! expA ) expA = 1;
104 }
105 sigZ = aSPtr->signif;
106 sigB = bSPtr->signif;
107 /*------------------------------------------------------------------------
108 *------------------------------------------------------------------------*/
109 roundPackRoutinePtr = softfloat_roundPackMToExtF80M;
110 expDiff = expA - expB;
111 if ( expDiff ) {
112 /*--------------------------------------------------------------------
113 *--------------------------------------------------------------------*/
114 extSigX[indexWord( 3, 2 )] = sigB>>32;
115 extSigX[indexWord( 3, 1 )] = sigB;
116 extSigX[indexWord( 3, 0 )] = 0;
117 softfloat_shiftRightJam96M( extSigX, expDiff, extSigX );
118 sigB =
119 (uint64_t) extSigX[indexWord( 3, 2 )]<<32
120 | extSigX[indexWord( 3, 1 )];
121 if ( negateB ) {
122 sigZ -= sigB;
123 sigZExtra = extSigX[indexWordLo( 3 )];
124 if ( sigZExtra ) {
125 --sigZ;
126 sigZExtra = -sigZExtra;
127 }
128 if ( ! (sigZ & UINT64_C( 0x8000000000000000 )) ) {
129 if ( sigZ & UINT64_C( 0x4000000000000000 ) ) {
130 --expA;
131 sigZ = sigZ<<1 | sigZExtra>>31;
132 sigZExtra <<= 1;
133 } else {
134 roundPackRoutinePtr = softfloat_normRoundPackMToExtF80M;
135 }
136 }
137 } else {
138 sigZ += sigB;
139 if ( sigZ & UINT64_C( 0x8000000000000000 ) ) goto sigZ;
140 sigZExtra = (uint32_t) sigZ<<31 | (extSigX[indexWordLo( 3 )] != 0);
141 goto completeNormAfterAdd;
142 }
143 } else {
144 /*--------------------------------------------------------------------
145 *--------------------------------------------------------------------*/
146 sigZExtra = 0;
147 if ( negateB ) {
148 if ( sigZ < sigB ) {
149 signZ = ! signZ;
150 sigZ = sigB - sigZ;
151 } else {
152 sigZ -= sigB;
153 if ( ! sigZ ) {
154 signZ = (softfloat_roundingMode == softfloat_round_min);
155 zSPtr->signExp = packToExtF80UI64( signZ, 0 );
156 zSPtr->signif = 0;
157 return;
158 }
159 }
160 roundPackRoutinePtr = softfloat_normRoundPackMToExtF80M;
161 } else {
162 sigZ += sigB;
163 if ( sigZ < sigB ) {
164 sigZExtra = (uint32_t) sigZ<<31;
165 completeNormAfterAdd:
166 ++expA;
167 sigZ = UINT64_C( 0x8000000000000000 ) | sigZ>>1;
168 } else {
169 if ( ! (sigZ & UINT64_C( 0x8000000000000000 )) ) {
170 roundPackRoutinePtr = softfloat_normRoundPackMToExtF80M;
171 }
172 }
173 }
174 }
175 extSigX[indexWord( 3, 0 )] = sigZExtra;
176 sigZ:
177 extSigX[indexWord( 3, 2 )] = sigZ>>32;
178 extSigX[indexWord( 3, 1 )] = sigZ;
179 /*------------------------------------------------------------------------
180 *------------------------------------------------------------------------*/
181 roundPack:
182 (*roundPackRoutinePtr)(
183 signZ, expA, extSigX, extF80_roundingPrecision, zSPtr );
184
185}
186
deps/SoftFloat-3e/source/s_addF128M.c deleted-211
...@@ -1,211 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44void
45 softfloat_addF128M(
46 const uint32_t *aWPtr,
47 const uint32_t *bWPtr,
48 uint32_t *zWPtr,
49 bool negateB
50 )
51{
52 uint32_t uiA96;
53 int32_t expA;
54 uint32_t uiB96;
55 int32_t expB;
56 uint32_t uiZ96;
57 bool signZ, signB;
58 const uint32_t *tempPtr;
59 uint32_t sig96A, sig96B;
60 int32_t expDiff;
61 uint_fast8_t
62 (*addCarryMRoutinePtr)(
63 uint_fast8_t,
64 const uint32_t *,
65 const uint32_t *,
66 uint_fast8_t,
67 uint32_t *
68 );
69 uint32_t extSigZ[5], wordSigZ;
70 uint_fast8_t carry;
71 void (*roundPackRoutinePtr)( bool, int32_t, uint32_t *, uint32_t * );
72
73 /*------------------------------------------------------------------------
74 *------------------------------------------------------------------------*/
75 uiA96 = aWPtr[indexWordHi( 4 )];
76 expA = expF128UI96( uiA96 );
77 uiB96 = bWPtr[indexWordHi( 4 )];
78 expB = expF128UI96( uiB96 );
79 /*------------------------------------------------------------------------
80 *------------------------------------------------------------------------*/
81 if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
82 if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return;
83 uiZ96 = uiA96;
84 if ( expB == 0x7FFF ) {
85 uiZ96 = uiB96 ^ packToF128UI96( negateB, 0, 0 );
86 if ( (expA == 0x7FFF) && (uiZ96 != uiA96) ) {
87 softfloat_invalidF128M( zWPtr );
88 return;
89 }
90 }
91 zWPtr[indexWordHi( 4 )] = uiZ96;
92 zWPtr[indexWord( 4, 2 )] = 0;
93 zWPtr[indexWord( 4, 1 )] = 0;
94 zWPtr[indexWord( 4, 0 )] = 0;
95 return;
96 }
97 /*------------------------------------------------------------------------
98 *------------------------------------------------------------------------*/
99 signZ = signF128UI96( uiA96 );
100 signB = signF128UI96( uiB96 ) ^ negateB;
101 negateB = (signZ != signB);
102 if ( (uint32_t) (uiA96<<1) < (uint32_t) (uiB96<<1) ) {
103 signZ = signB;
104 expA = expB;
105 expB = expF128UI96( uiA96 );
106 tempPtr = aWPtr;
107 aWPtr = bWPtr;
108 bWPtr = tempPtr;
109 uiA96 = uiB96;
110 uiB96 = bWPtr[indexWordHi( 4 )];
111 }
112 sig96A = fracF128UI96( uiA96 );
113 sig96B = fracF128UI96( uiB96 );
114 if ( expA ) {
115 --expA;
116 sig96A |= 0x00010000;
117 if ( expB ) {
118 --expB;
119 sig96B |= 0x00010000;
120 }
121 }
122 /*------------------------------------------------------------------------
123 *------------------------------------------------------------------------*/
124 addCarryMRoutinePtr =
125 negateB ? softfloat_addComplCarryM : softfloat_addCarryM;
126 expDiff = expA - expB;
127 if ( expDiff ) {
128 /*--------------------------------------------------------------------
129 *--------------------------------------------------------------------*/
130 extSigZ[indexWordHi( 5 )] = sig96B;
131 extSigZ[indexWord( 5, 3 )] = bWPtr[indexWord( 4, 2 )];
132 extSigZ[indexWord( 5, 2 )] = bWPtr[indexWord( 4, 1 )];
133 extSigZ[indexWord( 5, 1 )] = bWPtr[indexWord( 4, 0 )];
134 extSigZ[indexWord( 5, 0 )] = 0;
135 softfloat_shiftRightJam160M( extSigZ, expDiff, extSigZ );
136 sig96B = extSigZ[indexWordHi( 5 )];
137 carry = 0;
138 if ( negateB ) {
139 sig96B = ~sig96B;
140 wordSigZ = extSigZ[indexWordLo( 5 )];
141 extSigZ[indexWordLo( 5 )] = -wordSigZ;
142 carry = ! wordSigZ;
143 }
144 carry =
145 (*addCarryMRoutinePtr)(
146 3,
147 &aWPtr[indexMultiwordLo( 4, 3 )],
148 &extSigZ[indexMultiword( 5, 3, 1 )],
149 carry,
150 &extSigZ[indexMultiword( 5, 3, 1 )]
151 );
152 wordSigZ = sig96A + sig96B + carry;
153 } else {
154 /*--------------------------------------------------------------------
155 *--------------------------------------------------------------------*/
156 extSigZ[indexWordLo( 5 )] = 0;
157 carry =
158 (*addCarryMRoutinePtr)(
159 3,
160 &aWPtr[indexMultiwordLo( 4, 3 )],
161 &bWPtr[indexMultiwordLo( 4, 3 )],
162 negateB,
163 &extSigZ[indexMultiword( 5, 3, 1 )]
164 );
165 if ( negateB ) {
166 wordSigZ = sig96A + ~sig96B + carry;
167 if ( wordSigZ & 0x80000000 ) {
168 signZ = ! signZ;
169 carry =
170 softfloat_addComplCarry96M(
171 &bWPtr[indexMultiwordLo( 4, 3 )],
172 &aWPtr[indexMultiwordLo( 4, 3 )],
173 1,
174 &extSigZ[indexMultiword( 5, 3, 1 )]
175 );
176 wordSigZ = sig96B + ~sig96A + carry;
177 } else {
178 if (
179 ! wordSigZ && ! extSigZ[indexWord( 5, 3 )]
180 && ! ( extSigZ[indexWord( 5, 2 )]
181 | extSigZ[indexWord( 5, 1 )]
182 | extSigZ[indexWord( 5, 0 )]
183 )
184 ) {
185 signZ = (softfloat_roundingMode == softfloat_round_min);
186 zWPtr[indexWordHi( 4 )] = packToF128UI96( signZ, 0, 0 );
187 zWPtr[indexWord( 4, 2 )] = 0;
188 zWPtr[indexWord( 4, 1 )] = 0;
189 zWPtr[indexWord( 4, 0 )] = 0;
190 return;
191 }
192 }
193 } else {
194 wordSigZ = sig96A + sig96B + carry;
195 }
196 }
197 extSigZ[indexWordHi( 5 )] = wordSigZ;
198 /*------------------------------------------------------------------------
199 *------------------------------------------------------------------------*/
200 roundPackRoutinePtr = softfloat_normRoundPackMToF128M;
201 if ( 0x00010000 <= wordSigZ ) {
202 if ( 0x00020000 <= wordSigZ ) {
203 ++expA;
204 softfloat_shortShiftRightJam160M( extSigZ, 1, extSigZ );
205 }
206 roundPackRoutinePtr = softfloat_roundPackMToF128M;
207 }
208 (*roundPackRoutinePtr)( signZ, expA, extSigZ, zWPtr );
209
210}
211
deps/SoftFloat-3e/source/s_addM.c deleted-70
...@@ -1,70 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_addM
42
43void
44 softfloat_addM(
45 uint_fast8_t size_words,
46 const uint32_t *aPtr,
47 const uint32_t *bPtr,
48 uint32_t *zPtr
49 )
50{
51 unsigned int index, lastIndex;
52 uint_fast8_t carry;
53 uint32_t wordA, wordZ;
54
55 index = indexWordLo( size_words );
56 lastIndex = indexWordHi( size_words );
57 carry = 0;
58 for (;;) {
59 wordA = aPtr[index];
60 wordZ = wordA + bPtr[index] + carry;
61 zPtr[index] = wordZ;
62 if ( index == lastIndex ) break;
63 if ( wordZ != wordA ) carry = (wordZ < wordA);
64 index += wordIncr;
65 }
66
67}
68
69#endif
70
deps/SoftFloat-3e/source/s_addMagsExtF80.c deleted-156
...@@ -1,156 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44extFloat80_t
45 softfloat_addMagsExtF80(
46 uint_fast16_t uiA64,
47 uint_fast64_t uiA0,
48 uint_fast16_t uiB64,
49 uint_fast64_t uiB0,
50 bool signZ
51 )
52{
53 int_fast32_t expA;
54 uint_fast64_t sigA;
55 int_fast32_t expB;
56 uint_fast64_t sigB;
57 int_fast32_t expDiff;
58 uint_fast16_t uiZ64;
59 uint_fast64_t uiZ0, sigZ, sigZExtra;
60 struct exp32_sig64 normExpSig;
61 int_fast32_t expZ;
62 struct uint64_extra sig64Extra;
63 struct uint128 uiZ;
64 union { struct extFloat80M s; extFloat80_t f; } uZ;
65
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 expA = expExtF80UI64( uiA64 );
69 sigA = uiA0;
70 expB = expExtF80UI64( uiB64 );
71 sigB = uiB0;
72 /*------------------------------------------------------------------------
73 *------------------------------------------------------------------------*/
74 expDiff = expA - expB;
75 if ( ! expDiff ) {
76 if ( expA == 0x7FFF ) {
77 if ( (sigA | sigB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
78 goto propagateNaN;
79 }
80 uiZ64 = uiA64;
81 uiZ0 = uiA0;
82 goto uiZ;
83 }
84 sigZ = sigA + sigB;
85 sigZExtra = 0;
86 if ( ! expA ) {
87 normExpSig = softfloat_normSubnormalExtF80Sig( sigZ );
88 expZ = normExpSig.exp + 1;
89 sigZ = normExpSig.sig;
90 goto roundAndPack;
91 }
92 expZ = expA;
93 goto shiftRight1;
94 }
95 /*------------------------------------------------------------------------
96 *------------------------------------------------------------------------*/
97 if ( expDiff < 0 ) {
98 if ( expB == 0x7FFF ) {
99 if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN;
100 uiZ64 = packToExtF80UI64( signZ, 0x7FFF );
101 uiZ0 = uiB0;
102 goto uiZ;
103 }
104 expZ = expB;
105 if ( ! expA ) {
106 ++expDiff;
107 sigZExtra = 0;
108 if ( ! expDiff ) goto newlyAligned;
109 }
110 sig64Extra = softfloat_shiftRightJam64Extra( sigA, 0, -expDiff );
111 sigA = sig64Extra.v;
112 sigZExtra = sig64Extra.extra;
113 } else {
114 if ( expA == 0x7FFF ) {
115 if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN;
116 uiZ64 = uiA64;
117 uiZ0 = uiA0;
118 goto uiZ;
119 }
120 expZ = expA;
121 if ( ! expB ) {
122 --expDiff;
123 sigZExtra = 0;
124 if ( ! expDiff ) goto newlyAligned;
125 }
126 sig64Extra = softfloat_shiftRightJam64Extra( sigB, 0, expDiff );
127 sigB = sig64Extra.v;
128 sigZExtra = sig64Extra.extra;
129 }
130 newlyAligned:
131 sigZ = sigA + sigB;
132 if ( sigZ & UINT64_C( 0x8000000000000000 ) ) goto roundAndPack;
133 /*------------------------------------------------------------------------
134 *------------------------------------------------------------------------*/
135 shiftRight1:
136 sig64Extra = softfloat_shortShiftRightJam64Extra( sigZ, sigZExtra, 1 );
137 sigZ = sig64Extra.v | UINT64_C( 0x8000000000000000 );
138 sigZExtra = sig64Extra.extra;
139 ++expZ;
140 roundAndPack:
141 return
142 softfloat_roundPackToExtF80(
143 signZ, expZ, sigZ, sigZExtra, extF80_roundingPrecision );
144 /*------------------------------------------------------------------------
145 *------------------------------------------------------------------------*/
146 propagateNaN:
147 uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 );
148 uiZ64 = uiZ.v64;
149 uiZ0 = uiZ.v0;
150 uiZ:
151 uZ.s.signExp = uiZ64;
152 uZ.s.signif = uiZ0;
153 return uZ.f;
154
155}
156
deps/SoftFloat-3e/source/s_addMagsF128.c deleted-154
...@@ -1,154 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42
43float128_t
44 softfloat_addMagsF128(
45 uint_fast64_t uiA64,
46 uint_fast64_t uiA0,
47 uint_fast64_t uiB64,
48 uint_fast64_t uiB0,
49 bool signZ
50 )
51{
52 int_fast32_t expA;
53 struct uint128 sigA;
54 int_fast32_t expB;
55 struct uint128 sigB;
56 int_fast32_t expDiff;
57 struct uint128 uiZ, sigZ;
58 int_fast32_t expZ;
59 uint_fast64_t sigZExtra;
60 struct uint128_extra sig128Extra;
61 union ui128_f128 uZ;
62
63 expA = expF128UI64( uiA64 );
64 sigA.v64 = fracF128UI64( uiA64 );
65 sigA.v0 = uiA0;
66 expB = expF128UI64( uiB64 );
67 sigB.v64 = fracF128UI64( uiB64 );
68 sigB.v0 = uiB0;
69 expDiff = expA - expB;
70 if ( ! expDiff ) {
71 if ( expA == 0x7FFF ) {
72 if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN;
73 uiZ.v64 = uiA64;
74 uiZ.v0 = uiA0;
75 goto uiZ;
76 }
77 sigZ = softfloat_add128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 );
78 if ( ! expA ) {
79 uiZ.v64 = packToF128UI64( signZ, 0, sigZ.v64 );
80 uiZ.v0 = sigZ.v0;
81 goto uiZ;
82 }
83 expZ = expA;
84 sigZ.v64 |= UINT64_C( 0x0002000000000000 );
85 sigZExtra = 0;
86 goto shiftRight1;
87 }
88 if ( expDiff < 0 ) {
89 if ( expB == 0x7FFF ) {
90 if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
91 uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
92 uiZ.v0 = 0;
93 goto uiZ;
94 }
95 expZ = expB;
96 if ( expA ) {
97 sigA.v64 |= UINT64_C( 0x0001000000000000 );
98 } else {
99 ++expDiff;
100 sigZExtra = 0;
101 if ( ! expDiff ) goto newlyAligned;
102 }
103 sig128Extra =
104 softfloat_shiftRightJam128Extra( sigA.v64, sigA.v0, 0, -expDiff );
105 sigA = sig128Extra.v;
106 sigZExtra = sig128Extra.extra;
107 } else {
108 if ( expA == 0x7FFF ) {
109 if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
110 uiZ.v64 = uiA64;
111 uiZ.v0 = uiA0;
112 goto uiZ;
113 }
114 expZ = expA;
115 if ( expB ) {
116 sigB.v64 |= UINT64_C( 0x0001000000000000 );
117 } else {
118 --expDiff;
119 sigZExtra = 0;
120 if ( ! expDiff ) goto newlyAligned;
121 }
122 sig128Extra =
123 softfloat_shiftRightJam128Extra( sigB.v64, sigB.v0, 0, expDiff );
124 sigB = sig128Extra.v;
125 sigZExtra = sig128Extra.extra;
126 }
127 newlyAligned:
128 sigZ =
129 softfloat_add128(
130 sigA.v64 | UINT64_C( 0x0001000000000000 ),
131 sigA.v0,
132 sigB.v64,
133 sigB.v0
134 );
135 --expZ;
136 if ( sigZ.v64 < UINT64_C( 0x0002000000000000 ) ) goto roundAndPack;
137 ++expZ;
138 shiftRight1:
139 sig128Extra =
140 softfloat_shortShiftRightJam128Extra(
141 sigZ.v64, sigZ.v0, sigZExtra, 1 );
142 sigZ = sig128Extra.v;
143 sigZExtra = sig128Extra.extra;
144 roundAndPack:
145 return
146 softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
147 propagateNaN:
148 uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
149 uiZ:
150 uZ.ui = uiZ;
151 return uZ.f;
152
153}
154
deps/SoftFloat-3e/source/s_addMagsF16.c deleted-183
...@@ -1,183 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float16_t softfloat_addMagsF16( uint_fast16_t uiA, uint_fast16_t uiB )
45{
46 int_fast8_t expA;
47 uint_fast16_t sigA;
48 int_fast8_t expB;
49 uint_fast16_t sigB;
50 int_fast8_t expDiff;
51 uint_fast16_t uiZ;
52 bool signZ;
53 int_fast8_t expZ;
54 uint_fast16_t sigZ;
55 uint_fast16_t sigX, sigY;
56 int_fast8_t shiftDist;
57 uint_fast32_t sig32Z;
58 int_fast8_t roundingMode;
59 union ui16_f16 uZ;
60
61 /*------------------------------------------------------------------------
62 *------------------------------------------------------------------------*/
63 expA = expF16UI( uiA );
64 sigA = fracF16UI( uiA );
65 expB = expF16UI( uiB );
66 sigB = fracF16UI( uiB );
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 expDiff = expA - expB;
70 if ( ! expDiff ) {
71 /*--------------------------------------------------------------------
72 *--------------------------------------------------------------------*/
73 if ( ! expA ) {
74 uiZ = uiA + sigB;
75 goto uiZ;
76 }
77 if ( expA == 0x1F ) {
78 if ( sigA | sigB ) goto propagateNaN;
79 uiZ = uiA;
80 goto uiZ;
81 }
82 signZ = signF16UI( uiA );
83 expZ = expA;
84 sigZ = 0x0800 + sigA + sigB;
85 if ( ! (sigZ & 1) && (expZ < 0x1E) ) {
86 sigZ >>= 1;
87 goto pack;
88 }
89 sigZ <<= 3;
90 } else {
91 /*--------------------------------------------------------------------
92 *--------------------------------------------------------------------*/
93 signZ = signF16UI( uiA );
94 if ( expDiff < 0 ) {
95 /*----------------------------------------------------------------
96 *----------------------------------------------------------------*/
97 if ( expB == 0x1F ) {
98 if ( sigB ) goto propagateNaN;
99 uiZ = packToF16UI( signZ, 0x1F, 0 );
100 goto uiZ;
101 }
102 if ( expDiff <= -13 ) {
103 uiZ = packToF16UI( signZ, expB, sigB );
104 if ( expA | sigA ) goto addEpsilon;
105 goto uiZ;
106 }
107 expZ = expB;
108 sigX = sigB | 0x0400;
109 sigY = sigA + (expA ? 0x0400 : sigA);
110 shiftDist = 19 + expDiff;
111 } else {
112 /*----------------------------------------------------------------
113 *----------------------------------------------------------------*/
114 uiZ = uiA;
115 if ( expA == 0x1F ) {
116 if ( sigA ) goto propagateNaN;
117 goto uiZ;
118 }
119 if ( 13 <= expDiff ) {
120 if ( expB | sigB ) goto addEpsilon;
121 goto uiZ;
122 }
123 expZ = expA;
124 sigX = sigA | 0x0400;
125 sigY = sigB + (expB ? 0x0400 : sigB);
126 shiftDist = 19 - expDiff;
127 }
128 sig32Z =
129 ((uint_fast32_t) sigX<<19) + ((uint_fast32_t) sigY<<shiftDist);
130 if ( sig32Z < 0x40000000 ) {
131 --expZ;
132 sig32Z <<= 1;
133 }
134 sigZ = sig32Z>>16;
135 if ( sig32Z & 0xFFFF ) {
136 sigZ |= 1;
137 } else {
138 if ( ! (sigZ & 0xF) && (expZ < 0x1E) ) {
139 sigZ >>= 4;
140 goto pack;
141 }
142 }
143 }
144 return softfloat_roundPackToF16( signZ, expZ, sigZ );
145 /*------------------------------------------------------------------------
146 *------------------------------------------------------------------------*/
147 propagateNaN:
148 uiZ = softfloat_propagateNaNF16UI( uiA, uiB );
149 goto uiZ;
150 /*------------------------------------------------------------------------
151 *------------------------------------------------------------------------*/
152 addEpsilon:
153 roundingMode = softfloat_roundingMode;
154 if ( roundingMode != softfloat_round_near_even ) {
155 if (
156 roundingMode
157 == (signF16UI( uiZ ) ? softfloat_round_min
158 : softfloat_round_max)
159 ) {
160 ++uiZ;
161 if ( (uint16_t) (uiZ<<1) == 0xF800 ) {
162 softfloat_raiseFlags(
163 softfloat_flag_overflow | softfloat_flag_inexact );
164 }
165 }
166#ifdef SOFTFLOAT_ROUND_ODD
167 else if ( roundingMode == softfloat_round_odd ) {
168 uiZ |= 1;
169 }
170#endif
171 }
172 softfloat_exceptionFlags |= softfloat_flag_inexact;
173 goto uiZ;
174 /*------------------------------------------------------------------------
175 *------------------------------------------------------------------------*/
176 pack:
177 uiZ = packToF16UI( signZ, expZ, sigZ );
178 uiZ:
179 uZ.ui = uiZ;
180 return uZ.f;
181
182}
183
deps/SoftFloat-3e/source/s_addMagsF32.c deleted-126
...@@ -1,126 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42
43float32_t softfloat_addMagsF32( uint_fast32_t uiA, uint_fast32_t uiB )
44{
45 int_fast16_t expA;
46 uint_fast32_t sigA;
47 int_fast16_t expB;
48 uint_fast32_t sigB;
49 int_fast16_t expDiff;
50 uint_fast32_t uiZ;
51 bool signZ;
52 int_fast16_t expZ;
53 uint_fast32_t sigZ;
54 union ui32_f32 uZ;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 expA = expF32UI( uiA );
59 sigA = fracF32UI( uiA );
60 expB = expF32UI( uiB );
61 sigB = fracF32UI( uiB );
62 /*------------------------------------------------------------------------
63 *------------------------------------------------------------------------*/
64 expDiff = expA - expB;
65 if ( ! expDiff ) {
66 /*--------------------------------------------------------------------
67 *--------------------------------------------------------------------*/
68 if ( ! expA ) {
69 uiZ = uiA + sigB;
70 goto uiZ;
71 }
72 if ( expA == 0xFF ) {
73 if ( sigA | sigB ) goto propagateNaN;
74 uiZ = uiA;
75 goto uiZ;
76 }
77 signZ = signF32UI( uiA );
78 expZ = expA;
79 sigZ = 0x01000000 + sigA + sigB;
80 if ( ! (sigZ & 1) && (expZ < 0xFE) ) {
81 uiZ = packToF32UI( signZ, expZ, sigZ>>1 );
82 goto uiZ;
83 }
84 sigZ <<= 6;
85 } else {
86 /*--------------------------------------------------------------------
87 *--------------------------------------------------------------------*/
88 signZ = signF32UI( uiA );
89 sigA <<= 6;
90 sigB <<= 6;
91 if ( expDiff < 0 ) {
92 if ( expB == 0xFF ) {
93 if ( sigB ) goto propagateNaN;
94 uiZ = packToF32UI( signZ, 0xFF, 0 );
95 goto uiZ;
96 }
97 expZ = expB;
98 sigA += expA ? 0x20000000 : sigA;
99 sigA = softfloat_shiftRightJam32( sigA, -expDiff );
100 } else {
101 if ( expA == 0xFF ) {
102 if ( sigA ) goto propagateNaN;
103 uiZ = uiA;
104 goto uiZ;
105 }
106 expZ = expA;
107 sigB += expB ? 0x20000000 : sigB;
108 sigB = softfloat_shiftRightJam32( sigB, expDiff );
109 }
110 sigZ = 0x20000000 + sigA + sigB;
111 if ( sigZ < 0x40000000 ) {
112 --expZ;
113 sigZ <<= 1;
114 }
115 }
116 return softfloat_roundPackToF32( signZ, expZ, sigZ );
117 /*------------------------------------------------------------------------
118 *------------------------------------------------------------------------*/
119 propagateNaN:
120 uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
121 uiZ:
122 uZ.ui = uiZ;
123 return uZ.f;
124
125}
126
deps/SoftFloat-3e/source/s_addMagsF64.c deleted-128
...@@ -1,128 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42
43float64_t
44 softfloat_addMagsF64( uint_fast64_t uiA, uint_fast64_t uiB, bool signZ )
45{
46 int_fast16_t expA;
47 uint_fast64_t sigA;
48 int_fast16_t expB;
49 uint_fast64_t sigB;
50 int_fast16_t expDiff;
51 uint_fast64_t uiZ;
52 int_fast16_t expZ;
53 uint_fast64_t sigZ;
54 union ui64_f64 uZ;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 expA = expF64UI( uiA );
59 sigA = fracF64UI( uiA );
60 expB = expF64UI( uiB );
61 sigB = fracF64UI( uiB );
62 /*------------------------------------------------------------------------
63 *------------------------------------------------------------------------*/
64 expDiff = expA - expB;
65 if ( ! expDiff ) {
66 /*--------------------------------------------------------------------
67 *--------------------------------------------------------------------*/
68 if ( ! expA ) {
69 uiZ = uiA + sigB;
70 goto uiZ;
71 }
72 if ( expA == 0x7FF ) {
73 if ( sigA | sigB ) goto propagateNaN;
74 uiZ = uiA;
75 goto uiZ;
76 }
77 expZ = expA;
78 sigZ = UINT64_C( 0x0020000000000000 ) + sigA + sigB;
79 sigZ <<= 9;
80 } else {
81 /*--------------------------------------------------------------------
82 *--------------------------------------------------------------------*/
83 sigA <<= 9;
84 sigB <<= 9;
85 if ( expDiff < 0 ) {
86 if ( expB == 0x7FF ) {
87 if ( sigB ) goto propagateNaN;
88 uiZ = packToF64UI( signZ, 0x7FF, 0 );
89 goto uiZ;
90 }
91 expZ = expB;
92 if ( expA ) {
93 sigA += UINT64_C( 0x2000000000000000 );
94 } else {
95 sigA <<= 1;
96 }
97 sigA = softfloat_shiftRightJam64( sigA, -expDiff );
98 } else {
99 if ( expA == 0x7FF ) {
100 if ( sigA ) goto propagateNaN;
101 uiZ = uiA;
102 goto uiZ;
103 }
104 expZ = expA;
105 if ( expB ) {
106 sigB += UINT64_C( 0x2000000000000000 );
107 } else {
108 sigB <<= 1;
109 }
110 sigB = softfloat_shiftRightJam64( sigB, expDiff );
111 }
112 sigZ = UINT64_C( 0x2000000000000000 ) + sigA + sigB;
113 if ( sigZ < UINT64_C( 0x4000000000000000 ) ) {
114 --expZ;
115 sigZ <<= 1;
116 }
117 }
118 return softfloat_roundPackToF64( signZ, expZ, sigZ );
119 /*------------------------------------------------------------------------
120 *------------------------------------------------------------------------*/
121 propagateNaN:
122 uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
123 uiZ:
124 uZ.ui = uiZ;
125 return uZ.f;
126
127}
128
deps/SoftFloat-3e/source/s_approxRecip32_1.c deleted-66
...@@ -1,66 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39
40#ifndef softfloat_approxRecip32_1
41
42extern const uint16_t softfloat_approxRecip_1k0s[16];
43extern const uint16_t softfloat_approxRecip_1k1s[16];
44
45uint32_t softfloat_approxRecip32_1( uint32_t a )
46{
47 int index;
48 uint16_t eps, r0;
49 uint32_t sigma0;
50 uint_fast32_t r;
51 uint32_t sqrSigma0;
52
53 index = a>>27 & 0xF;
54 eps = (uint16_t) (a>>11);
55 r0 = softfloat_approxRecip_1k0s[index]
56 - ((softfloat_approxRecip_1k1s[index] * (uint_fast32_t) eps)>>20);
57 sigma0 = ~(uint_fast32_t) ((r0 * (uint_fast64_t) a)>>7);
58 r = ((uint_fast32_t) r0<<16) + ((r0 * (uint_fast64_t) sigma0)>>24);
59 sqrSigma0 = ((uint_fast64_t) sigma0 * sigma0)>>32;
60 r += ((uint32_t) r * (uint_fast64_t) sqrSigma0)>>48;
61 return r;
62
63}
64
65#endif
66
deps/SoftFloat-3e/source/s_approxRecipSqrt32_1.c deleted-73
...@@ -1,73 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39
40#ifndef softfloat_approxRecipSqrt32_1
41
42extern const uint16_t softfloat_approxRecipSqrt_1k0s[];
43extern const uint16_t softfloat_approxRecipSqrt_1k1s[];
44
45uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a )
46{
47 int index;
48 uint16_t eps, r0;
49 uint_fast32_t ESqrR0;
50 uint32_t sigma0;
51 uint_fast32_t r;
52 uint32_t sqrSigma0;
53
54 index = (a>>27 & 0xE) + oddExpA;
55 eps = (uint16_t) (a>>12);
56 r0 = softfloat_approxRecipSqrt_1k0s[index]
57 - ((softfloat_approxRecipSqrt_1k1s[index] * (uint_fast32_t) eps)
58 >>20);
59 ESqrR0 = (uint_fast32_t) r0 * r0;
60 if ( ! oddExpA ) ESqrR0 <<= 1;
61 sigma0 = ~(uint_fast32_t) (((uint32_t) ESqrR0 * (uint_fast64_t) a)>>23);
62 r = ((uint_fast32_t) r0<<16) + ((r0 * (uint_fast64_t) sigma0)>>25);
63 sqrSigma0 = ((uint_fast64_t) sigma0 * sigma0)>>32;
64 r += ((uint32_t) ((r>>1) + (r>>3) - ((uint_fast32_t) r0<<14))
65 * (uint_fast64_t) sqrSigma0)
66 >>48;
67 if ( ! (r & 0x80000000) ) r = 0x80000000;
68 return r;
69
70}
71
72#endif
73
deps/SoftFloat-3e/source/s_approxRecipSqrt_1Ks.c deleted-49
...@@ -1,49 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40
41const uint16_t softfloat_approxRecipSqrt_1k0s[16] = {
42 0xB4C9, 0xFFAB, 0xAA7D, 0xF11C, 0xA1C5, 0xE4C7, 0x9A43, 0xDA29,
43 0x93B5, 0xD0E5, 0x8DED, 0xC8B7, 0x88C6, 0xC16D, 0x8424, 0xBAE1
44};
45const uint16_t softfloat_approxRecipSqrt_1k1s[16] = {
46 0xA5A5, 0xEA42, 0x8C21, 0xC62D, 0x788F, 0xAA7F, 0x6928, 0x94B6,
47 0x5CC7, 0x8335, 0x52A6, 0x74E2, 0x4A3E, 0x68FE, 0x432B, 0x5EFD
48};
49
deps/SoftFloat-3e/source/s_approxRecip_1Ks.c deleted-49
...@@ -1,49 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40
41const uint16_t softfloat_approxRecip_1k0s[16] = {
42 0xFFC4, 0xF0BE, 0xE363, 0xD76F, 0xCCAD, 0xC2F0, 0xBA16, 0xB201,
43 0xAA97, 0xA3C6, 0x9D7A, 0x97A6, 0x923C, 0x8D32, 0x887E, 0x8417
44};
45const uint16_t softfloat_approxRecip_1k1s[16] = {
46 0xF0F1, 0xD62C, 0xBFA1, 0xAC77, 0x9C0A, 0x8DDB, 0x8185, 0x76BA,
47 0x6D3B, 0x64D4, 0x5D5C, 0x56B1, 0x50B6, 0x4B55, 0x4679, 0x4211
48};
49
deps/SoftFloat-3e/source/s_compare128M.c deleted-62
...@@ -1,62 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_compare128M
42
43int_fast8_t softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr )
44{
45 unsigned int index, lastIndex;
46 uint32_t wordA, wordB;
47
48 index = indexWordHi( 4 );
49 lastIndex = indexWordLo( 4 );
50 for (;;) {
51 wordA = aPtr[index];
52 wordB = bPtr[index];
53 if ( wordA != wordB ) return (wordA < wordB) ? -1 : 1;
54 if ( index == lastIndex ) break;
55 index -= wordIncr;
56 }
57 return 0;
58
59}
60
61#endif
62
deps/SoftFloat-3e/source/s_compare96M.c deleted-62
...@@ -1,62 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_compare96M
42
43int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr )
44{
45 unsigned int index, lastIndex;
46 uint32_t wordA, wordB;
47
48 index = indexWordHi( 3 );
49 lastIndex = indexWordLo( 3 );
50 for (;;) {
51 wordA = aPtr[index];
52 wordB = bPtr[index];
53 if ( wordA != wordB ) return (wordA < wordB) ? -1 : 1;
54 if ( index == lastIndex ) break;
55 index -= wordIncr;
56 }
57 return 0;
58
59}
60
61#endif
62
deps/SoftFloat-3e/source/s_compareNonnormExtF80M.c deleted-111
...@@ -1,111 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat_types.h"
41
42int
43 softfloat_compareNonnormExtF80M(
44 const struct extFloat80M *aSPtr, const struct extFloat80M *bSPtr )
45{
46 uint_fast16_t uiA64, uiB64;
47 uint64_t sigA;
48 bool signB;
49 uint64_t sigB;
50 int32_t expA, expB;
51
52 /*------------------------------------------------------------------------
53 *------------------------------------------------------------------------*/
54 uiA64 = aSPtr->signExp;
55 uiB64 = bSPtr->signExp;
56 sigA = aSPtr->signif;
57 signB = signExtF80UI64( uiB64 );
58 sigB = bSPtr->signif;
59 /*------------------------------------------------------------------------
60 *------------------------------------------------------------------------*/
61 if ( (uiA64 ^ uiB64) & 0x8000 ) {
62 if ( ! (sigA | sigB) ) return 0;
63 goto resultFromSignB;
64 }
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 expA = expExtF80UI64( uiA64 );
68 expB = expExtF80UI64( uiB64 );
69 if ( expA == 0x7FFF ) {
70 if (expB == 0x7FFF) return 0;
71 signB = ! signB;
72 goto resultFromSignB;
73 }
74 if ( expB == 0x7FFF ) {
75 goto resultFromSignB;
76 }
77 /*------------------------------------------------------------------------
78 *------------------------------------------------------------------------*/
79 if ( ! expA ) expA = 1;
80 if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) {
81 if ( sigA ) {
82 expA += softfloat_normExtF80SigM( &sigA );
83 } else {
84 expA = -128;
85 }
86 }
87 if ( ! expB ) expB = 1;
88 if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) {
89 if ( sigB ) {
90 expB += softfloat_normExtF80SigM( &sigB );
91 } else {
92 expB = -128;
93 }
94 }
95 /*------------------------------------------------------------------------
96 *------------------------------------------------------------------------*/
97 if ( signB ) {
98 if ( expA < expB ) return 1;
99 if ( (expB < expA) || (sigB < sigA) ) return -1;
100 } else {
101 if ( expB < expA ) return 1;
102 if ( (expA < expB) || (sigA < sigB) ) return -1;
103 }
104 return (sigA != sigB);
105 /*------------------------------------------------------------------------
106 *------------------------------------------------------------------------*/
107 resultFromSignB:
108 return signB ? 1 : -1;
109
110}
111
deps/SoftFloat-3e/source/s_countLeadingZeros16.c deleted-60
...@@ -1,60 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39
40#ifndef softfloat_countLeadingZeros16
41
42#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16
43#include "primitives.h"
44
45uint_fast8_t softfloat_countLeadingZeros16( uint16_t a )
46{
47 uint_fast8_t count;
48
49 count = 8;
50 if ( 0x100 <= a ) {
51 count = 0;
52 a >>= 8;
53 }
54 count += softfloat_countLeadingZeros8[a];
55 return count;
56
57}
58
59#endif
60
deps/SoftFloat-3e/source/s_countLeadingZeros32.c deleted-64
...@@ -1,64 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39
40#ifndef softfloat_countLeadingZeros32
41
42#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32
43#include "primitives.h"
44
45uint_fast8_t softfloat_countLeadingZeros32( uint32_t a )
46{
47 uint_fast8_t count;
48
49 count = 0;
50 if ( a < 0x10000 ) {
51 count = 16;
52 a <<= 16;
53 }
54 if ( a < 0x1000000 ) {
55 count += 8;
56 a <<= 8;
57 }
58 count += softfloat_countLeadingZeros8[a>>24];
59 return count;
60
61}
62
63#endif
64
deps/SoftFloat-3e/source/s_countLeadingZeros64.c deleted-73
...@@ -1,73 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39
40#ifndef softfloat_countLeadingZeros64
41
42#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64
43#include "primitives.h"
44
45uint_fast8_t softfloat_countLeadingZeros64( uint64_t a )
46{
47 uint_fast8_t count;
48 uint32_t a32;
49
50 count = 0;
51 a32 = a>>32;
52 if ( ! a32 ) {
53 count = 32;
54 a32 = a;
55 }
56 /*------------------------------------------------------------------------
57 | From here, result is current count + count leading zeros of `a32'.
58 *------------------------------------------------------------------------*/
59 if ( a32 < 0x10000 ) {
60 count += 16;
61 a32 <<= 16;
62 }
63 if ( a32 < 0x1000000 ) {
64 count += 8;
65 a32 <<= 8;
66 }
67 count += softfloat_countLeadingZeros8[a32>>24];
68 return count;
69
70}
71
72#endif
73
deps/SoftFloat-3e/source/s_countLeadingZeros8.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40
41const uint_least8_t softfloat_countLeadingZeros8[256] = {
42 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
43 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
44 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
45 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
46 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
47 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
48 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
49 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
50 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
58};
59
deps/SoftFloat-3e/source/s_eq128.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40
41#ifndef softfloat_eq128
42
43bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
44{
45
46 return (a64 == b64) && (a0 == b0);
47
48}
49
50#endif
51
deps/SoftFloat-3e/source/s_invalidExtF80M.c deleted-49
...@@ -1,49 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include "platform.h"
38#include "specialize.h"
39#include "softfloat.h"
40
41void softfloat_invalidExtF80M( struct extFloat80M *zSPtr )
42{
43
44 softfloat_raiseFlags( softfloat_flag_invalid );
45 zSPtr->signExp = defaultNaNExtF80UI64;
46 zSPtr->signif = defaultNaNExtF80UI0;
47
48}
49
deps/SoftFloat-3e/source/s_invalidF128M.c deleted-53
...@@ -1,53 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitives.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43void softfloat_invalidF128M( uint32_t *zWPtr )
44{
45
46 softfloat_raiseFlags( softfloat_flag_invalid );
47 zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96;
48 zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64;
49 zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32;
50 zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0;
51
52}
53
deps/SoftFloat-3e/source/s_isNaNF128M.c deleted-57
...@@ -1,57 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "primitives.h"
41
42/*----------------------------------------------------------------------------
43*----------------------------------------------------------------------------*/
44bool softfloat_isNaNF128M( const uint32_t *aWPtr )
45{
46 uint32_t uiA96;
47
48 uiA96 = aWPtr[indexWordHi( 4 )];
49 if ( (~uiA96 & 0x7FFF0000) != 0 ) return false;
50 return
51 ((uiA96 & 0x0000FFFF) != 0)
52 || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
53 | aWPtr[indexWord( 4, 0 )])
54 != 0);
55
56}
57
deps/SoftFloat-3e/source/s_le128.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40
41#ifndef softfloat_le128
42
43bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
44{
45
46 return (a64 < b64) || ((a64 == b64) && (a0 <= b0));
47
48}
49
50#endif
51
deps/SoftFloat-3e/source/s_lt128.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40
41#ifndef softfloat_lt128
42
43bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
44{
45
46 return (a64 < b64) || ((a64 == b64) && (a0 < b0));
47
48}
49
50#endif
51
deps/SoftFloat-3e/source/s_mul128By32.c deleted-58
...@@ -1,58 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_mul128By32
42
43struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b )
44{
45 struct uint128 z;
46 uint_fast64_t mid;
47 uint_fast32_t carry;
48
49 z.v0 = a0 * b;
50 mid = (uint_fast64_t) (uint32_t) (a0>>32) * b;
51 carry = (uint32_t) ((uint_fast32_t) (z.v0>>32) - (uint_fast32_t) mid);
52 z.v64 = a64 * b + (uint_fast32_t) ((mid + carry)>>32);
53 return z;
54
55}
56
57#endif
58
deps/SoftFloat-3e/source/s_mul128MTo256M.c deleted-100
...@@ -1,100 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_mul128MTo256M
42
43void
44 softfloat_mul128MTo256M(
45 const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr )
46{
47 uint32_t *lastZPtr, wordB;
48 uint64_t dwordProd;
49 uint32_t wordZ;
50 uint_fast8_t carry;
51
52 bPtr += indexWordLo( 4 );
53 lastZPtr = zPtr + indexMultiwordHi( 8, 5 );
54 zPtr += indexMultiwordLo( 8, 5 );
55 wordB = *bPtr;
56 dwordProd = (uint64_t) aPtr[indexWord( 4, 0 )] * wordB;
57 zPtr[indexWord( 5, 0 )] = dwordProd;
58 dwordProd = (uint64_t) aPtr[indexWord( 4, 1 )] * wordB + (dwordProd>>32);
59 zPtr[indexWord( 5, 1 )] = dwordProd;
60 dwordProd = (uint64_t) aPtr[indexWord( 4, 2 )] * wordB + (dwordProd>>32);
61 zPtr[indexWord( 5, 2 )] = dwordProd;
62 dwordProd = (uint64_t) aPtr[indexWord( 4, 3 )] * wordB + (dwordProd>>32);
63 zPtr[indexWord( 5, 3 )] = dwordProd;
64 zPtr[indexWord( 5, 4 )] = dwordProd>>32;
65 do {
66 bPtr += wordIncr;
67 zPtr += wordIncr;
68 wordB = *bPtr;
69 dwordProd = (uint64_t) aPtr[indexWord( 4, 0 )] * wordB;
70 wordZ = zPtr[indexWord( 5, 0 )] + (uint32_t) dwordProd;
71 zPtr[indexWord( 5, 0 )] = wordZ;
72 carry = (wordZ < (uint32_t) dwordProd);
73 dwordProd =
74 (uint64_t) aPtr[indexWord( 4, 1 )] * wordB + (dwordProd>>32);
75 wordZ = zPtr[indexWord( 5, 1 )] + (uint32_t) dwordProd + carry;
76 zPtr[indexWord( 5, 1 )] = wordZ;
77 if ( wordZ != (uint32_t) dwordProd ) {
78 carry = (wordZ < (uint32_t) dwordProd);
79 }
80 dwordProd =
81 (uint64_t) aPtr[indexWord( 4, 2 )] * wordB + (dwordProd>>32);
82 wordZ = zPtr[indexWord( 5, 2 )] + (uint32_t) dwordProd + carry;
83 zPtr[indexWord( 5, 2 )] = wordZ;
84 if ( wordZ != (uint32_t) dwordProd ) {
85 carry = (wordZ < (uint32_t) dwordProd);
86 }
87 dwordProd =
88 (uint64_t) aPtr[indexWord( 4, 3 )] * wordB + (dwordProd>>32);
89 wordZ = zPtr[indexWord( 5, 3 )] + (uint32_t) dwordProd + carry;
90 zPtr[indexWord( 5, 3 )] = wordZ;
91 if ( wordZ != (uint32_t) dwordProd ) {
92 carry = (wordZ < (uint32_t) dwordProd);
93 }
94 zPtr[indexWord( 5, 4 )] = (dwordProd>>32) + carry;
95 } while ( zPtr != lastZPtr );
96
97}
98
99#endif
100
deps/SoftFloat-3e/source/s_mul128To256M.c deleted-71
...@@ -1,71 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39
40#ifndef softfloat_mul128To256M
41
42#define softfloat_mul128To256M softfloat_mul128To256M
43#include "primitives.h"
44
45void
46 softfloat_mul128To256M(
47 uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr )
48{
49 struct uint128 p0, p64, p128;
50 uint_fast64_t z64, z128, z192;
51
52 p0 = softfloat_mul64To128( a0, b0 );
53 zPtr[indexWord( 4, 0 )] = p0.v0;
54 p64 = softfloat_mul64To128( a64, b0 );
55 z64 = p64.v0 + p0.v64;
56 z128 = p64.v64 + (z64 < p64.v0);
57 p128 = softfloat_mul64To128( a64, b64 );
58 z128 += p128.v0;
59 z192 = p128.v64 + (z128 < p128.v0);
60 p64 = softfloat_mul64To128( a0, b64 );
61 z64 += p64.v0;
62 zPtr[indexWord( 4, 1 )] = z64;
63 p64.v64 += (z64 < p64.v0);
64 z128 += p64.v64;
65 zPtr[indexWord( 4, 2 )] = z128;
66 zPtr[indexWord( 4, 3 )] = z192 + (z128 < p64.v64);
67
68}
69
70#endif
71
deps/SoftFloat-3e/source/s_mul64ByShifted32To128.c deleted-56
...@@ -1,56 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_mul64ByShifted32To128
42
43struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b )
44{
45 uint_fast64_t mid;
46 struct uint128 z;
47
48 mid = (uint_fast64_t) (uint32_t) a * b;
49 z.v0 = mid<<32;
50 z.v64 = (uint_fast64_t) (uint32_t) (a>>32) * b + (mid>>32);
51 return z;
52
53}
54
55#endif
56
deps/SoftFloat-3e/source/s_mul64To128.c deleted-66
...@@ -1,66 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_mul64To128
42
43struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b )
44{
45 uint32_t a32, a0, b32, b0;
46 struct uint128 z;
47 uint64_t mid1, mid;
48
49 a32 = a>>32;
50 a0 = a;
51 b32 = b>>32;
52 b0 = b;
53 z.v0 = (uint_fast64_t) a0 * b0;
54 mid1 = (uint_fast64_t) a32 * b0;
55 mid = mid1 + (uint_fast64_t) a0 * b32;
56 z.v64 = (uint_fast64_t) a32 * b32;
57 z.v64 += (uint_fast64_t) (mid < mid1)<<32 | mid>>32;
58 mid <<= 32;
59 z.v0 += mid;
60 z.v64 += (z.v0 < mid);
61 return z;
62
63}
64
65#endif
66
deps/SoftFloat-3e/source/s_mul64To128M.c deleted-68
...@@ -1,68 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_mul64To128M
42
43void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr )
44{
45 uint32_t a32, a0, b32, b0;
46 uint64_t z0, mid1, z64, mid;
47
48 a32 = a>>32;
49 a0 = a;
50 b32 = b>>32;
51 b0 = b;
52 z0 = (uint64_t) a0 * b0;
53 mid1 = (uint64_t) a32 * b0;
54 mid = mid1 + (uint64_t) a0 * b32;
55 z64 = (uint64_t) a32 * b32;
56 z64 += (uint64_t) (mid < mid1)<<32 | mid>>32;
57 mid <<= 32;
58 z0 += mid;
59 zPtr[indexWord( 4, 1 )] = z0>>32;
60 zPtr[indexWord( 4, 0 )] = z0;
61 z64 += (z0 < mid);
62 zPtr[indexWord( 4, 3 )] = z64>>32;
63 zPtr[indexWord( 4, 2 )] = z64;
64
65}
66
67#endif
68
deps/SoftFloat-3e/source/s_mulAddF128.c deleted-350
...@@ -1,350 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float128_t
45 softfloat_mulAddF128(
46 uint_fast64_t uiA64,
47 uint_fast64_t uiA0,
48 uint_fast64_t uiB64,
49 uint_fast64_t uiB0,
50 uint_fast64_t uiC64,
51 uint_fast64_t uiC0,
52 uint_fast8_t op
53 )
54{
55 bool signA;
56 int_fast32_t expA;
57 struct uint128 sigA;
58 bool signB;
59 int_fast32_t expB;
60 struct uint128 sigB;
61 bool signC;
62 int_fast32_t expC;
63 struct uint128 sigC;
64 bool signZ;
65 uint_fast64_t magBits;
66 struct uint128 uiZ;
67 struct exp32_sig128 normExpSig;
68 int_fast32_t expZ;
69 uint64_t sig256Z[4];
70 struct uint128 sigZ;
71 int_fast32_t shiftDist, expDiff;
72 struct uint128 x128;
73 uint64_t sig256C[4];
74 static uint64_t zero256[4] = INIT_UINTM4( 0, 0, 0, 0 );
75 uint_fast64_t sigZExtra, sig256Z0;
76 union ui128_f128 uZ;
77
78 /*------------------------------------------------------------------------
79 *------------------------------------------------------------------------*/
80 signA = signF128UI64( uiA64 );
81 expA = expF128UI64( uiA64 );
82 sigA.v64 = fracF128UI64( uiA64 );
83 sigA.v0 = uiA0;
84 signB = signF128UI64( uiB64 );
85 expB = expF128UI64( uiB64 );
86 sigB.v64 = fracF128UI64( uiB64 );
87 sigB.v0 = uiB0;
88 signC = signF128UI64( uiC64 ) ^ (op == softfloat_mulAdd_subC);
89 expC = expF128UI64( uiC64 );
90 sigC.v64 = fracF128UI64( uiC64 );
91 sigC.v0 = uiC0;
92 signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd);
93 /*------------------------------------------------------------------------
94 *------------------------------------------------------------------------*/
95 if ( expA == 0x7FFF ) {
96 if (
97 (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))
98 ) {
99 goto propagateNaN_ABC;
100 }
101 magBits = expB | sigB.v64 | sigB.v0;
102 goto infProdArg;
103 }
104 if ( expB == 0x7FFF ) {
105 if ( sigB.v64 | sigB.v0 ) goto propagateNaN_ABC;
106 magBits = expA | sigA.v64 | sigA.v0;
107 goto infProdArg;
108 }
109 if ( expC == 0x7FFF ) {
110 if ( sigC.v64 | sigC.v0 ) {
111 uiZ.v64 = 0;
112 uiZ.v0 = 0;
113 goto propagateNaN_ZC;
114 }
115 uiZ.v64 = uiC64;
116 uiZ.v0 = uiC0;
117 goto uiZ;
118 }
119 /*------------------------------------------------------------------------
120 *------------------------------------------------------------------------*/
121 if ( ! expA ) {
122 if ( ! (sigA.v64 | sigA.v0) ) goto zeroProd;
123 normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
124 expA = normExpSig.exp;
125 sigA = normExpSig.sig;
126 }
127 if ( ! expB ) {
128 if ( ! (sigB.v64 | sigB.v0) ) goto zeroProd;
129 normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
130 expB = normExpSig.exp;
131 sigB = normExpSig.sig;
132 }
133 /*------------------------------------------------------------------------
134 *------------------------------------------------------------------------*/
135 expZ = expA + expB - 0x3FFE;
136 sigA.v64 |= UINT64_C( 0x0001000000000000 );
137 sigB.v64 |= UINT64_C( 0x0001000000000000 );
138 sigA = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 8 );
139 sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 15 );
140 softfloat_mul128To256M( sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z );
141 sigZ.v64 = sig256Z[indexWord( 4, 3 )];
142 sigZ.v0 = sig256Z[indexWord( 4, 2 )];
143 shiftDist = 0;
144 if ( ! (sigZ.v64 & UINT64_C( 0x0100000000000000 )) ) {
145 --expZ;
146 shiftDist = -1;
147 }
148 if ( ! expC ) {
149 if ( ! (sigC.v64 | sigC.v0) ) {
150 shiftDist += 8;
151 goto sigZ;
152 }
153 normExpSig = softfloat_normSubnormalF128Sig( sigC.v64, sigC.v0 );
154 expC = normExpSig.exp;
155 sigC = normExpSig.sig;
156 }
157 sigC.v64 |= UINT64_C( 0x0001000000000000 );
158 sigC = softfloat_shortShiftLeft128( sigC.v64, sigC.v0, 8 );
159 /*------------------------------------------------------------------------
160 *------------------------------------------------------------------------*/
161 expDiff = expZ - expC;
162 if ( expDiff < 0 ) {
163 expZ = expC;
164 if ( (signZ == signC) || (expDiff < -1) ) {
165 shiftDist -= expDiff;
166 if ( shiftDist ) {
167 sigZ =
168 softfloat_shiftRightJam128( sigZ.v64, sigZ.v0, shiftDist );
169 }
170 } else {
171 if ( ! shiftDist ) {
172 x128 =
173 softfloat_shortShiftRight128(
174 sig256Z[indexWord( 4, 1 )], sig256Z[indexWord( 4, 0 )],
175 1
176 );
177 sig256Z[indexWord( 4, 1 )] = (sigZ.v0<<63) | x128.v64;
178 sig256Z[indexWord( 4, 0 )] = x128.v0;
179 sigZ = softfloat_shortShiftRight128( sigZ.v64, sigZ.v0, 1 );
180 sig256Z[indexWord( 4, 3 )] = sigZ.v64;
181 sig256Z[indexWord( 4, 2 )] = sigZ.v0;
182 }
183 }
184 } else {
185 if ( shiftDist ) softfloat_add256M( sig256Z, sig256Z, sig256Z );
186 if ( ! expDiff ) {
187 sigZ.v64 = sig256Z[indexWord( 4, 3 )];
188 sigZ.v0 = sig256Z[indexWord( 4, 2 )];
189 } else {
190 sig256C[indexWord( 4, 3 )] = sigC.v64;
191 sig256C[indexWord( 4, 2 )] = sigC.v0;
192 sig256C[indexWord( 4, 1 )] = 0;
193 sig256C[indexWord( 4, 0 )] = 0;
194 softfloat_shiftRightJam256M( sig256C, expDiff, sig256C );
195 }
196 }
197 /*------------------------------------------------------------------------
198 *------------------------------------------------------------------------*/
199 shiftDist = 8;
200 if ( signZ == signC ) {
201 /*--------------------------------------------------------------------
202 *--------------------------------------------------------------------*/
203 if ( expDiff <= 0 ) {
204 sigZ = softfloat_add128( sigC.v64, sigC.v0, sigZ.v64, sigZ.v0 );
205 } else {
206 softfloat_add256M( sig256Z, sig256C, sig256Z );
207 sigZ.v64 = sig256Z[indexWord( 4, 3 )];
208 sigZ.v0 = sig256Z[indexWord( 4, 2 )];
209 }
210 if ( sigZ.v64 & UINT64_C( 0x0200000000000000 ) ) {
211 ++expZ;
212 shiftDist = 9;
213 }
214 } else {
215 /*--------------------------------------------------------------------
216 *--------------------------------------------------------------------*/
217 if ( expDiff < 0 ) {
218 signZ = signC;
219 if ( expDiff < -1 ) {
220 sigZ =
221 softfloat_sub128( sigC.v64, sigC.v0, sigZ.v64, sigZ.v0 );
222 sigZExtra =
223 sig256Z[indexWord( 4, 1 )] | sig256Z[indexWord( 4, 0 )];
224 if ( sigZExtra ) {
225 sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, 0, 1 );
226 }
227 if ( ! (sigZ.v64 & UINT64_C( 0x0100000000000000 )) ) {
228 --expZ;
229 shiftDist = 7;
230 }
231 goto shiftRightRoundPack;
232 } else {
233 sig256C[indexWord( 4, 3 )] = sigC.v64;
234 sig256C[indexWord( 4, 2 )] = sigC.v0;
235 sig256C[indexWord( 4, 1 )] = 0;
236 sig256C[indexWord( 4, 0 )] = 0;
237 softfloat_sub256M( sig256C, sig256Z, sig256Z );
238 }
239 } else if ( ! expDiff ) {
240 sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, sigC.v64, sigC.v0 );
241 if (
242 ! (sigZ.v64 | sigZ.v0) && ! sig256Z[indexWord( 4, 1 )]
243 && ! sig256Z[indexWord( 4, 0 )]
244 ) {
245 goto completeCancellation;
246 }
247 sig256Z[indexWord( 4, 3 )] = sigZ.v64;
248 sig256Z[indexWord( 4, 2 )] = sigZ.v0;
249 if ( sigZ.v64 & UINT64_C( 0x8000000000000000 ) ) {
250 signZ = ! signZ;
251 softfloat_sub256M( zero256, sig256Z, sig256Z );
252 }
253 } else {
254 softfloat_sub256M( sig256Z, sig256C, sig256Z );
255 if ( 1 < expDiff ) {
256 sigZ.v64 = sig256Z[indexWord( 4, 3 )];
257 sigZ.v0 = sig256Z[indexWord( 4, 2 )];
258 if ( ! (sigZ.v64 & UINT64_C( 0x0100000000000000 )) ) {
259 --expZ;
260 shiftDist = 7;
261 }
262 goto sigZ;
263 }
264 }
265 /*--------------------------------------------------------------------
266 *--------------------------------------------------------------------*/
267 sigZ.v64 = sig256Z[indexWord( 4, 3 )];
268 sigZ.v0 = sig256Z[indexWord( 4, 2 )];
269 sigZExtra = sig256Z[indexWord( 4, 1 )];
270 sig256Z0 = sig256Z[indexWord( 4, 0 )];
271 if ( sigZ.v64 ) {
272 if ( sig256Z0 ) sigZExtra |= 1;
273 } else {
274 expZ -= 64;
275 sigZ.v64 = sigZ.v0;
276 sigZ.v0 = sigZExtra;
277 sigZExtra = sig256Z0;
278 if ( ! sigZ.v64 ) {
279 expZ -= 64;
280 sigZ.v64 = sigZ.v0;
281 sigZ.v0 = sigZExtra;
282 sigZExtra = 0;
283 if ( ! sigZ.v64 ) {
284 expZ -= 64;
285 sigZ.v64 = sigZ.v0;
286 sigZ.v0 = 0;
287 }
288 }
289 }
290 shiftDist = softfloat_countLeadingZeros64( sigZ.v64 );
291 expZ += 7 - shiftDist;
292 shiftDist = 15 - shiftDist;
293 if ( 0 < shiftDist ) goto shiftRightRoundPack;
294 if ( shiftDist ) {
295 shiftDist = -shiftDist;
296 sigZ = softfloat_shortShiftLeft128( sigZ.v64, sigZ.v0, shiftDist );
297 x128 = softfloat_shortShiftLeft128( 0, sigZExtra, shiftDist );
298 sigZ.v0 |= x128.v64;
299 sigZExtra = x128.v0;
300 }
301 goto roundPack;
302 }
303 sigZ:
304 sigZExtra = sig256Z[indexWord( 4, 1 )] | sig256Z[indexWord( 4, 0 )];
305 shiftRightRoundPack:
306 sigZExtra = (uint64_t) (sigZ.v0<<(64 - shiftDist)) | (sigZExtra != 0);
307 sigZ = softfloat_shortShiftRight128( sigZ.v64, sigZ.v0, shiftDist );
308 roundPack:
309 return
310 softfloat_roundPackToF128(
311 signZ, expZ - 1, sigZ.v64, sigZ.v0, sigZExtra );
312 /*------------------------------------------------------------------------
313 *------------------------------------------------------------------------*/
314 propagateNaN_ABC:
315 uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
316 goto propagateNaN_ZC;
317 /*------------------------------------------------------------------------
318 *------------------------------------------------------------------------*/
319 infProdArg:
320 if ( magBits ) {
321 uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
322 uiZ.v0 = 0;
323 if ( expC != 0x7FFF ) goto uiZ;
324 if ( sigC.v64 | sigC.v0 ) goto propagateNaN_ZC;
325 if ( signZ == signC ) goto uiZ;
326 }
327 softfloat_raiseFlags( softfloat_flag_invalid );
328 uiZ.v64 = defaultNaNF128UI64;
329 uiZ.v0 = defaultNaNF128UI0;
330 propagateNaN_ZC:
331 uiZ = softfloat_propagateNaNF128UI( uiZ.v64, uiZ.v0, uiC64, uiC0 );
332 goto uiZ;
333 /*------------------------------------------------------------------------
334 *------------------------------------------------------------------------*/
335 zeroProd:
336 uiZ.v64 = uiC64;
337 uiZ.v0 = uiC0;
338 if ( ! (expC | sigC.v64 | sigC.v0) && (signZ != signC) ) {
339 completeCancellation:
340 uiZ.v64 =
341 packToF128UI64(
342 (softfloat_roundingMode == softfloat_round_min), 0, 0 );
343 uiZ.v0 = 0;
344 }
345 uiZ:
346 uZ.ui = uiZ;
347 return uZ.f;
348
349}
350
deps/SoftFloat-3e/source/s_mulAddF128M.c deleted-382
...@@ -1,382 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44void
45 softfloat_mulAddF128M(
46 const uint32_t *aWPtr,
47 const uint32_t *bWPtr,
48 const uint32_t *cWPtr,
49 uint32_t *zWPtr,
50 uint_fast8_t op
51 )
52{
53 uint32_t uiA96;
54 int32_t expA;
55 uint32_t uiB96;
56 int32_t expB;
57 uint32_t uiC96;
58 bool signC;
59 int32_t expC;
60 bool signProd, prodIsInfinite;
61 uint32_t *ptr, uiZ96, sigA[4];
62 uint_fast8_t shiftDist;
63 uint32_t sigX[5];
64 int32_t expProd;
65 uint32_t sigProd[8], wordSig;
66 bool doSub;
67 uint_fast8_t
68 (*addCarryMRoutinePtr)(
69 uint_fast8_t,
70 const uint32_t *,
71 const uint32_t *,
72 uint_fast8_t,
73 uint32_t *
74 );
75 int32_t expDiff;
76 bool signZ;
77 int32_t expZ;
78 uint32_t *extSigPtr;
79 uint_fast8_t carry;
80 void (*roundPackRoutinePtr)( bool, int32_t, uint32_t *, uint32_t * );
81
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 uiA96 = aWPtr[indexWordHi( 4 )];
85 expA = expF128UI96( uiA96 );
86 uiB96 = bWPtr[indexWordHi( 4 )];
87 expB = expF128UI96( uiB96 );
88 uiC96 = cWPtr[indexWordHi( 4 )];
89 signC = signF128UI96( uiC96 ) ^ (op == softfloat_mulAdd_subC);
90 expC = expF128UI96( uiC96 );
91 signProd =
92 signF128UI96( uiA96 ) ^ signF128UI96( uiB96 )
93 ^ (op == softfloat_mulAdd_subProd);
94 /*------------------------------------------------------------------------
95 *------------------------------------------------------------------------*/
96 prodIsInfinite = false;
97 if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
98 if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) {
99 goto propagateNaN_ZC;
100 }
101 ptr = (uint32_t *) aWPtr;
102 if ( ! (uint32_t) (uiA96<<1) ) goto possibleInvalidProd;
103 if ( ! (uint32_t) (uiB96<<1) ) {
104 ptr = (uint32_t *) bWPtr;
105 possibleInvalidProd:
106 if (
107 ! (ptr[indexWord( 4, 2 )] | ptr[indexWord( 4, 1 )]
108 | ptr[indexWord( 4, 0 )])
109 ) {
110 goto invalid;
111 }
112 }
113 prodIsInfinite = true;
114 }
115 if ( expC == 0x7FFF ) {
116 if (
117 fracF128UI96( uiC96 )
118 || (cWPtr[indexWord( 4, 2 )] | cWPtr[indexWord( 4, 1 )]
119 | cWPtr[indexWord( 4, 0 )])
120 ) {
121 zWPtr[indexWordHi( 4 )] = 0;
122 goto propagateNaN_ZC;
123 }
124 if ( prodIsInfinite && (signProd != signC) ) goto invalid;
125 goto copyC;
126 }
127 if ( prodIsInfinite ) {
128 uiZ96 = packToF128UI96( signProd, 0x7FFF, 0 );
129 goto uiZ;
130 }
131 /*------------------------------------------------------------------------
132 *------------------------------------------------------------------------*/
133 if ( expA ) {
134 sigA[indexWordHi( 4 )] = fracF128UI96( uiA96 ) | 0x00010000;
135 sigA[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )];
136 sigA[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )];
137 sigA[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )];
138 } else {
139 expA = softfloat_shiftNormSigF128M( aWPtr, 0, sigA );
140 if ( expA == -128 ) goto zeroProd;
141 }
142 if ( expB ) {
143 sigX[indexWordHi( 4 )] = fracF128UI96( uiB96 ) | 0x00010000;
144 sigX[indexWord( 4, 2 )] = bWPtr[indexWord( 4, 2 )];
145 sigX[indexWord( 4, 1 )] = bWPtr[indexWord( 4, 1 )];
146 sigX[indexWord( 4, 0 )] = bWPtr[indexWord( 4, 0 )];
147 } else {
148 expB = softfloat_shiftNormSigF128M( bWPtr, 0, sigX );
149 if ( expB == -128 ) goto zeroProd;
150 }
151 /*------------------------------------------------------------------------
152 *------------------------------------------------------------------------*/
153 expProd = expA + expB - 0x3FF0;
154 softfloat_mul128MTo256M( sigA, sigX, sigProd );
155 /*------------------------------------------------------------------------
156 *------------------------------------------------------------------------*/
157 wordSig = fracF128UI96( uiC96 );
158 if ( expC ) {
159 --expC;
160 wordSig |= 0x00010000;
161 }
162 sigX[indexWordHi( 5 )] = wordSig;
163 sigX[indexWord( 5, 3 )] = cWPtr[indexWord( 4, 2 )];
164 sigX[indexWord( 5, 2 )] = cWPtr[indexWord( 4, 1 )];
165 sigX[indexWord( 5, 1 )] = cWPtr[indexWord( 4, 0 )];
166 /*------------------------------------------------------------------------
167 *------------------------------------------------------------------------*/
168 doSub = (signProd != signC);
169 addCarryMRoutinePtr =
170 doSub ? softfloat_addComplCarryM : softfloat_addCarryM;
171 expDiff = expProd - expC;
172 if ( expDiff <= 0 ) {
173 /*--------------------------------------------------------------------
174 *--------------------------------------------------------------------*/
175 signZ = signC;
176 expZ = expC;
177 if (
178 sigProd[indexWord( 8, 2 )]
179 || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )])
180 ) {
181 sigProd[indexWord( 8, 3 )] |= 1;
182 }
183 extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )];
184 if ( expDiff ) {
185 softfloat_shiftRightJam160M( extSigPtr, -expDiff, extSigPtr );
186 }
187 carry = 0;
188 if ( doSub ) {
189 wordSig = extSigPtr[indexWordLo( 5 )];
190 extSigPtr[indexWordLo( 5 )] = -wordSig;
191 carry = ! wordSig;
192 }
193 (*addCarryMRoutinePtr)(
194 4,
195 &sigX[indexMultiwordHi( 5, 4 )],
196 extSigPtr + indexMultiwordHi( 5, 4 ),
197 carry,
198 extSigPtr + indexMultiwordHi( 5, 4 )
199 );
200 wordSig = extSigPtr[indexWordHi( 5 )];
201 if ( ! expZ ) {
202 if ( wordSig & 0x80000000 ) {
203 signZ = ! signZ;
204 softfloat_negX160M( extSigPtr );
205 wordSig = extSigPtr[indexWordHi( 5 )];
206 }
207 goto checkCancellation;
208 }
209 if ( wordSig < 0x00010000 ) {
210 --expZ;
211 softfloat_add160M( extSigPtr, extSigPtr, extSigPtr );
212 goto roundPack;
213 }
214 goto extSigReady_noCancellation;
215 } else {
216 /*--------------------------------------------------------------------
217 *--------------------------------------------------------------------*/
218 signZ = signProd;
219 expZ = expProd;
220 sigX[indexWordLo( 5 )] = 0;
221 expDiff -= 128;
222 if ( 0 <= expDiff ) {
223 /*----------------------------------------------------------------
224 *----------------------------------------------------------------*/
225 if ( expDiff ) softfloat_shiftRightJam160M( sigX, expDiff, sigX );
226 wordSig = sigX[indexWordLo( 5 )];
227 carry = 0;
228 if ( doSub ) {
229 carry = ! wordSig;
230 wordSig = -wordSig;
231 }
232 carry =
233 (*addCarryMRoutinePtr)(
234 4,
235 &sigProd[indexMultiwordLo( 8, 4 )],
236 &sigX[indexMultiwordHi( 5, 4 )],
237 carry,
238 &sigProd[indexMultiwordLo( 8, 4 )]
239 );
240 sigProd[indexWord( 8, 2 )] |= wordSig;
241 ptr = &sigProd[indexWord( 8, 4 )];
242 } else {
243 /*----------------------------------------------------------------
244 *----------------------------------------------------------------*/
245 shiftDist = expDiff & 31;
246 if ( shiftDist ) {
247 softfloat_shortShiftRight160M( sigX, shiftDist, sigX );
248 }
249 expDiff >>= 5;
250 extSigPtr =
251 &sigProd[indexMultiwordLo( 8, 5 )] - wordIncr
252 + expDiff * -wordIncr;
253 carry =
254 (*addCarryMRoutinePtr)( 5, extSigPtr, sigX, doSub, extSigPtr );
255 if ( expDiff == -4 ) {
256 /*------------------------------------------------------------
257 *------------------------------------------------------------*/
258 wordSig = sigProd[indexWordHi( 8 )];
259 if ( wordSig & 0x80000000 ) {
260 signZ = ! signZ;
261 softfloat_negX256M( sigProd );
262 wordSig = sigProd[indexWordHi( 8 )];
263 }
264 /*------------------------------------------------------------
265 *------------------------------------------------------------*/
266 if ( wordSig ) goto expProdBigger_noWordShift;
267 wordSig = sigProd[indexWord( 8, 6 )];
268 if ( 0x00040000 <= wordSig ) goto expProdBigger_noWordShift;
269 expZ -= 32;
270 extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )] - wordIncr;
271 for (;;) {
272 if ( wordSig ) break;
273 wordSig = extSigPtr[indexWord( 5, 3 )];
274 if ( 0x00040000 <= wordSig ) break;
275 expZ -= 32;
276 extSigPtr -= wordIncr;
277 if ( extSigPtr == &sigProd[indexMultiwordLo( 8, 5 )] ) {
278 goto checkCancellation;
279 }
280 }
281 /*------------------------------------------------------------
282 *------------------------------------------------------------*/
283 ptr = extSigPtr + indexWordLo( 5 );
284 do {
285 ptr -= wordIncr;
286 if ( *ptr ) {
287 extSigPtr[indexWordLo( 5 )] |= 1;
288 break;
289 }
290 } while ( ptr != &sigProd[indexWordLo( 8 )] );
291 wordSig = extSigPtr[indexWordHi( 5 )];
292 goto extSigReady;
293 }
294 ptr = extSigPtr + indexWordHi( 5 ) + wordIncr;
295 }
296 /*--------------------------------------------------------------------
297 *--------------------------------------------------------------------*/
298 if ( carry != doSub ) {
299 if ( doSub ) {
300 do {
301 wordSig = *ptr;
302 *ptr = wordSig - 1;
303 ptr += wordIncr;
304 } while ( ! wordSig );
305 } else {
306 do {
307 wordSig = *ptr + 1;
308 *ptr = wordSig;
309 ptr += wordIncr;
310 } while ( ! wordSig );
311 }
312 }
313 /*--------------------------------------------------------------------
314 *--------------------------------------------------------------------*/
315 expProdBigger_noWordShift:
316 if (
317 sigProd[indexWord( 8, 2 )]
318 || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )])
319 ) {
320 sigProd[indexWord( 8, 3 )] |= 1;
321 }
322 extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )];
323 wordSig = extSigPtr[indexWordHi( 5 )];
324 }
325 extSigReady:
326 roundPackRoutinePtr = softfloat_normRoundPackMToF128M;
327 if ( wordSig < 0x00010000 ) goto doRoundPack;
328 extSigReady_noCancellation:
329 if ( 0x00020000 <= wordSig ) {
330 ++expZ;
331 softfloat_shortShiftRightJam160M( extSigPtr, 1, extSigPtr );
332 }
333 roundPack:
334 roundPackRoutinePtr = softfloat_roundPackMToF128M;
335 doRoundPack:
336 (*roundPackRoutinePtr)( signZ, expZ, extSigPtr, zWPtr );
337 return;
338 /*------------------------------------------------------------------------
339 *------------------------------------------------------------------------*/
340 invalid:
341 softfloat_invalidF128M( zWPtr );
342 propagateNaN_ZC:
343 softfloat_propagateNaNF128M( zWPtr, cWPtr, zWPtr );
344 return;
345 /*------------------------------------------------------------------------
346 *------------------------------------------------------------------------*/
347 zeroProd:
348 if (
349 ! (uint32_t) (uiC96<<1) && (signProd != signC)
350 && ! cWPtr[indexWord( 4, 2 )]
351 && ! (cWPtr[indexWord( 4, 1 )] | cWPtr[indexWord( 4, 0 )])
352 ) {
353 goto completeCancellation;
354 }
355 copyC:
356 zWPtr[indexWordHi( 4 )] = uiC96;
357 zWPtr[indexWord( 4, 2 )] = cWPtr[indexWord( 4, 2 )];
358 zWPtr[indexWord( 4, 1 )] = cWPtr[indexWord( 4, 1 )];
359 zWPtr[indexWord( 4, 0 )] = cWPtr[indexWord( 4, 0 )];
360 return;
361 /*------------------------------------------------------------------------
362 *------------------------------------------------------------------------*/
363 checkCancellation:
364 if (
365 wordSig
366 || (extSigPtr[indexWord( 5, 3 )] | extSigPtr[indexWord( 5, 2 )])
367 || (extSigPtr[indexWord( 5, 1 )] | extSigPtr[indexWord( 5, 0 )])
368 ) {
369 goto extSigReady;
370 }
371 completeCancellation:
372 uiZ96 =
373 packToF128UI96(
374 (softfloat_roundingMode == softfloat_round_min), 0, 0 );
375 uiZ:
376 zWPtr[indexWordHi( 4 )] = uiZ96;
377 zWPtr[indexWord( 4, 2 )] = 0;
378 zWPtr[indexWord( 4, 1 )] = 0;
379 zWPtr[indexWord( 4, 0 )] = 0;
380
381}
382
deps/SoftFloat-3e/source/s_mulAddF16.c deleted-226
...@@ -1,226 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float16_t
45 softfloat_mulAddF16(
46 uint_fast16_t uiA, uint_fast16_t uiB, uint_fast16_t uiC, uint_fast8_t op )
47{
48 bool signA;
49 int_fast8_t expA;
50 uint_fast16_t sigA;
51 bool signB;
52 int_fast8_t expB;
53 uint_fast16_t sigB;
54 bool signC;
55 int_fast8_t expC;
56 uint_fast16_t sigC;
57 bool signProd;
58 uint_fast16_t magBits, uiZ;
59 struct exp8_sig16 normExpSig;
60 int_fast8_t expProd;
61 uint_fast32_t sigProd;
62 bool signZ;
63 int_fast8_t expZ;
64 uint_fast16_t sigZ;
65 int_fast8_t expDiff;
66 uint_fast32_t sig32Z, sig32C;
67 int_fast8_t shiftDist;
68 union ui16_f16 uZ;
69
70 /*------------------------------------------------------------------------
71 *------------------------------------------------------------------------*/
72 signA = signF16UI( uiA );
73 expA = expF16UI( uiA );
74 sigA = fracF16UI( uiA );
75 signB = signF16UI( uiB );
76 expB = expF16UI( uiB );
77 sigB = fracF16UI( uiB );
78 signC = signF16UI( uiC ) ^ (op == softfloat_mulAdd_subC);
79 expC = expF16UI( uiC );
80 sigC = fracF16UI( uiC );
81 signProd = signA ^ signB ^ (op == softfloat_mulAdd_subProd);
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( expA == 0x1F ) {
85 if ( sigA || ((expB == 0x1F) && sigB) ) goto propagateNaN_ABC;
86 magBits = expB | sigB;
87 goto infProdArg;
88 }
89 if ( expB == 0x1F ) {
90 if ( sigB ) goto propagateNaN_ABC;
91 magBits = expA | sigA;
92 goto infProdArg;
93 }
94 if ( expC == 0x1F ) {
95 if ( sigC ) {
96 uiZ = 0;
97 goto propagateNaN_ZC;
98 }
99 uiZ = uiC;
100 goto uiZ;
101 }
102 /*------------------------------------------------------------------------
103 *------------------------------------------------------------------------*/
104 if ( ! expA ) {
105 if ( ! sigA ) goto zeroProd;
106 normExpSig = softfloat_normSubnormalF16Sig( sigA );
107 expA = normExpSig.exp;
108 sigA = normExpSig.sig;
109 }
110 if ( ! expB ) {
111 if ( ! sigB ) goto zeroProd;
112 normExpSig = softfloat_normSubnormalF16Sig( sigB );
113 expB = normExpSig.exp;
114 sigB = normExpSig.sig;
115 }
116 /*------------------------------------------------------------------------
117 *------------------------------------------------------------------------*/
118 expProd = expA + expB - 0xE;
119 sigA = (sigA | 0x0400)<<4;
120 sigB = (sigB | 0x0400)<<4;
121 sigProd = (uint_fast32_t) sigA * sigB;
122 if ( sigProd < 0x20000000 ) {
123 --expProd;
124 sigProd <<= 1;
125 }
126 signZ = signProd;
127 if ( ! expC ) {
128 if ( ! sigC ) {
129 expZ = expProd - 1;
130 sigZ = sigProd>>15 | ((sigProd & 0x7FFF) != 0);
131 goto roundPack;
132 }
133 normExpSig = softfloat_normSubnormalF16Sig( sigC );
134 expC = normExpSig.exp;
135 sigC = normExpSig.sig;
136 }
137 sigC = (sigC | 0x0400)<<3;
138 /*------------------------------------------------------------------------
139 *------------------------------------------------------------------------*/
140 expDiff = expProd - expC;
141 if ( signProd == signC ) {
142 /*--------------------------------------------------------------------
143 *--------------------------------------------------------------------*/
144 if ( expDiff <= 0 ) {
145 expZ = expC;
146 sigZ = sigC + softfloat_shiftRightJam32( sigProd, 16 - expDiff );
147 } else {
148 expZ = expProd;
149 sig32Z =
150 sigProd
151 + softfloat_shiftRightJam32(
152 (uint_fast32_t) sigC<<16, expDiff );
153 sigZ = sig32Z>>16 | ((sig32Z & 0xFFFF) != 0 );
154 }
155 if ( sigZ < 0x4000 ) {
156 --expZ;
157 sigZ <<= 1;
158 }
159 } else {
160 /*--------------------------------------------------------------------
161 *--------------------------------------------------------------------*/
162 sig32C = (uint_fast32_t) sigC<<16;
163 if ( expDiff < 0 ) {
164 signZ = signC;
165 expZ = expC;
166 sig32Z = sig32C - softfloat_shiftRightJam32( sigProd, -expDiff );
167 } else if ( ! expDiff ) {
168 expZ = expProd;
169 sig32Z = sigProd - sig32C;
170 if ( ! sig32Z ) goto completeCancellation;
171 if ( sig32Z & 0x80000000 ) {
172 signZ = ! signZ;
173 sig32Z = -sig32Z;
174 }
175 } else {
176 expZ = expProd;
177 sig32Z = sigProd - softfloat_shiftRightJam32( sig32C, expDiff );
178 }
179 shiftDist = softfloat_countLeadingZeros32( sig32Z ) - 1;
180 expZ -= shiftDist;
181 shiftDist -= 16;
182 if ( shiftDist < 0 ) {
183 sigZ =
184 sig32Z>>(-shiftDist)
185 | ((uint32_t) (sig32Z<<(shiftDist & 31)) != 0);
186 } else {
187 sigZ = (uint_fast16_t) sig32Z<<shiftDist;
188 }
189 }
190 roundPack:
191 return softfloat_roundPackToF16( signZ, expZ, sigZ );
192 /*------------------------------------------------------------------------
193 *------------------------------------------------------------------------*/
194 propagateNaN_ABC:
195 uiZ = softfloat_propagateNaNF16UI( uiA, uiB );
196 goto propagateNaN_ZC;
197 /*------------------------------------------------------------------------
198 *------------------------------------------------------------------------*/
199 infProdArg:
200 if ( magBits ) {
201 uiZ = packToF16UI( signProd, 0x1F, 0 );
202 if ( expC != 0x1F ) goto uiZ;
203 if ( sigC ) goto propagateNaN_ZC;
204 if ( signProd == signC ) goto uiZ;
205 }
206 softfloat_raiseFlags( softfloat_flag_invalid );
207 uiZ = defaultNaNF16UI;
208 propagateNaN_ZC:
209 uiZ = softfloat_propagateNaNF16UI( uiZ, uiC );
210 goto uiZ;
211 /*------------------------------------------------------------------------
212 *------------------------------------------------------------------------*/
213 zeroProd:
214 uiZ = uiC;
215 if ( ! (expC | sigC) && (signProd != signC) ) {
216 completeCancellation:
217 uiZ =
218 packToF16UI(
219 (softfloat_roundingMode == softfloat_round_min), 0, 0 );
220 }
221 uiZ:
222 uZ.ui = uiZ;
223 return uZ.f;
224
225}
226
deps/SoftFloat-3e/source/s_mulAddF32.c deleted-224
...@@ -1,224 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float32_t
45 softfloat_mulAddF32(
46 uint_fast32_t uiA, uint_fast32_t uiB, uint_fast32_t uiC, uint_fast8_t op )
47{
48 bool signA;
49 int_fast16_t expA;
50 uint_fast32_t sigA;
51 bool signB;
52 int_fast16_t expB;
53 uint_fast32_t sigB;
54 bool signC;
55 int_fast16_t expC;
56 uint_fast32_t sigC;
57 bool signProd;
58 uint_fast32_t magBits, uiZ;
59 struct exp16_sig32 normExpSig;
60 int_fast16_t expProd;
61 uint_fast64_t sigProd;
62 bool signZ;
63 int_fast16_t expZ;
64 uint_fast32_t sigZ;
65 int_fast16_t expDiff;
66 uint_fast64_t sig64Z, sig64C;
67 int_fast8_t shiftDist;
68 union ui32_f32 uZ;
69
70 /*------------------------------------------------------------------------
71 *------------------------------------------------------------------------*/
72 signA = signF32UI( uiA );
73 expA = expF32UI( uiA );
74 sigA = fracF32UI( uiA );
75 signB = signF32UI( uiB );
76 expB = expF32UI( uiB );
77 sigB = fracF32UI( uiB );
78 signC = signF32UI( uiC ) ^ (op == softfloat_mulAdd_subC);
79 expC = expF32UI( uiC );
80 sigC = fracF32UI( uiC );
81 signProd = signA ^ signB ^ (op == softfloat_mulAdd_subProd);
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( expA == 0xFF ) {
85 if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN_ABC;
86 magBits = expB | sigB;
87 goto infProdArg;
88 }
89 if ( expB == 0xFF ) {
90 if ( sigB ) goto propagateNaN_ABC;
91 magBits = expA | sigA;
92 goto infProdArg;
93 }
94 if ( expC == 0xFF ) {
95 if ( sigC ) {
96 uiZ = 0;
97 goto propagateNaN_ZC;
98 }
99 uiZ = uiC;
100 goto uiZ;
101 }
102 /*------------------------------------------------------------------------
103 *------------------------------------------------------------------------*/
104 if ( ! expA ) {
105 if ( ! sigA ) goto zeroProd;
106 normExpSig = softfloat_normSubnormalF32Sig( sigA );
107 expA = normExpSig.exp;
108 sigA = normExpSig.sig;
109 }
110 if ( ! expB ) {
111 if ( ! sigB ) goto zeroProd;
112 normExpSig = softfloat_normSubnormalF32Sig( sigB );
113 expB = normExpSig.exp;
114 sigB = normExpSig.sig;
115 }
116 /*------------------------------------------------------------------------
117 *------------------------------------------------------------------------*/
118 expProd = expA + expB - 0x7E;
119 sigA = (sigA | 0x00800000)<<7;
120 sigB = (sigB | 0x00800000)<<7;
121 sigProd = (uint_fast64_t) sigA * sigB;
122 if ( sigProd < UINT64_C( 0x2000000000000000 ) ) {
123 --expProd;
124 sigProd <<= 1;
125 }
126 signZ = signProd;
127 if ( ! expC ) {
128 if ( ! sigC ) {
129 expZ = expProd - 1;
130 sigZ = softfloat_shortShiftRightJam64( sigProd, 31 );
131 goto roundPack;
132 }
133 normExpSig = softfloat_normSubnormalF32Sig( sigC );
134 expC = normExpSig.exp;
135 sigC = normExpSig.sig;
136 }
137 sigC = (sigC | 0x00800000)<<6;
138 /*------------------------------------------------------------------------
139 *------------------------------------------------------------------------*/
140 expDiff = expProd - expC;
141 if ( signProd == signC ) {
142 /*--------------------------------------------------------------------
143 *--------------------------------------------------------------------*/
144 if ( expDiff <= 0 ) {
145 expZ = expC;
146 sigZ = sigC + softfloat_shiftRightJam64( sigProd, 32 - expDiff );
147 } else {
148 expZ = expProd;
149 sig64Z =
150 sigProd
151 + softfloat_shiftRightJam64(
152 (uint_fast64_t) sigC<<32, expDiff );
153 sigZ = softfloat_shortShiftRightJam64( sig64Z, 32 );
154 }
155 if ( sigZ < 0x40000000 ) {
156 --expZ;
157 sigZ <<= 1;
158 }
159 } else {
160 /*--------------------------------------------------------------------
161 *--------------------------------------------------------------------*/
162 sig64C = (uint_fast64_t) sigC<<32;
163 if ( expDiff < 0 ) {
164 signZ = signC;
165 expZ = expC;
166 sig64Z = sig64C - softfloat_shiftRightJam64( sigProd, -expDiff );
167 } else if ( ! expDiff ) {
168 expZ = expProd;
169 sig64Z = sigProd - sig64C;
170 if ( ! sig64Z ) goto completeCancellation;
171 if ( sig64Z & UINT64_C( 0x8000000000000000 ) ) {
172 signZ = ! signZ;
173 sig64Z = -sig64Z;
174 }
175 } else {
176 expZ = expProd;
177 sig64Z = sigProd - softfloat_shiftRightJam64( sig64C, expDiff );
178 }
179 shiftDist = softfloat_countLeadingZeros64( sig64Z ) - 1;
180 expZ -= shiftDist;
181 shiftDist -= 32;
182 if ( shiftDist < 0 ) {
183 sigZ = softfloat_shortShiftRightJam64( sig64Z, -shiftDist );
184 } else {
185 sigZ = (uint_fast32_t) sig64Z<<shiftDist;
186 }
187 }
188 roundPack:
189 return softfloat_roundPackToF32( signZ, expZ, sigZ );
190 /*------------------------------------------------------------------------
191 *------------------------------------------------------------------------*/
192 propagateNaN_ABC:
193 uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
194 goto propagateNaN_ZC;
195 /*------------------------------------------------------------------------
196 *------------------------------------------------------------------------*/
197 infProdArg:
198 if ( magBits ) {
199 uiZ = packToF32UI( signProd, 0xFF, 0 );
200 if ( expC != 0xFF ) goto uiZ;
201 if ( sigC ) goto propagateNaN_ZC;
202 if ( signProd == signC ) goto uiZ;
203 }
204 softfloat_raiseFlags( softfloat_flag_invalid );
205 uiZ = defaultNaNF32UI;
206 propagateNaN_ZC:
207 uiZ = softfloat_propagateNaNF32UI( uiZ, uiC );
208 goto uiZ;
209 /*------------------------------------------------------------------------
210 *------------------------------------------------------------------------*/
211 zeroProd:
212 uiZ = uiC;
213 if ( ! (expC | sigC) && (signProd != signC) ) {
214 completeCancellation:
215 uiZ =
216 packToF32UI(
217 (softfloat_roundingMode == softfloat_round_min), 0, 0 );
218 }
219 uiZ:
220 uZ.ui = uiZ;
221 return uZ.f;
222
223}
224
deps/SoftFloat-3e/source/s_mulAddF64.c deleted-496
...@@ -1,496 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44#ifdef SOFTFLOAT_FAST_INT64
45
46float64_t
47 softfloat_mulAddF64(
48 uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC, uint_fast8_t op )
49{
50 bool signA;
51 int_fast16_t expA;
52 uint_fast64_t sigA;
53 bool signB;
54 int_fast16_t expB;
55 uint_fast64_t sigB;
56 bool signC;
57 int_fast16_t expC;
58 uint_fast64_t sigC;
59 bool signZ;
60 uint_fast64_t magBits, uiZ;
61 struct exp16_sig64 normExpSig;
62 int_fast16_t expZ;
63 struct uint128 sig128Z;
64 uint_fast64_t sigZ;
65 int_fast16_t expDiff;
66 struct uint128 sig128C;
67 int_fast8_t shiftDist;
68 union ui64_f64 uZ;
69
70 /*------------------------------------------------------------------------
71 *------------------------------------------------------------------------*/
72 signA = signF64UI( uiA );
73 expA = expF64UI( uiA );
74 sigA = fracF64UI( uiA );
75 signB = signF64UI( uiB );
76 expB = expF64UI( uiB );
77 sigB = fracF64UI( uiB );
78 signC = signF64UI( uiC ) ^ (op == softfloat_mulAdd_subC);
79 expC = expF64UI( uiC );
80 sigC = fracF64UI( uiC );
81 signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd);
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( expA == 0x7FF ) {
85 if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN_ABC;
86 magBits = expB | sigB;
87 goto infProdArg;
88 }
89 if ( expB == 0x7FF ) {
90 if ( sigB ) goto propagateNaN_ABC;
91 magBits = expA | sigA;
92 goto infProdArg;
93 }
94 if ( expC == 0x7FF ) {
95 if ( sigC ) {
96 uiZ = 0;
97 goto propagateNaN_ZC;
98 }
99 uiZ = uiC;
100 goto uiZ;
101 }
102 /*------------------------------------------------------------------------
103 *------------------------------------------------------------------------*/
104 if ( ! expA ) {
105 if ( ! sigA ) goto zeroProd;
106 normExpSig = softfloat_normSubnormalF64Sig( sigA );
107 expA = normExpSig.exp;
108 sigA = normExpSig.sig;
109 }
110 if ( ! expB ) {
111 if ( ! sigB ) goto zeroProd;
112 normExpSig = softfloat_normSubnormalF64Sig( sigB );
113 expB = normExpSig.exp;
114 sigB = normExpSig.sig;
115 }
116 /*------------------------------------------------------------------------
117 *------------------------------------------------------------------------*/
118 expZ = expA + expB - 0x3FE;
119 sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10;
120 sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<10;
121 sig128Z = softfloat_mul64To128( sigA, sigB );
122 if ( sig128Z.v64 < UINT64_C( 0x2000000000000000 ) ) {
123 --expZ;
124 sig128Z =
125 softfloat_add128(
126 sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0 );
127 }
128 if ( ! expC ) {
129 if ( ! sigC ) {
130 --expZ;
131 sigZ = sig128Z.v64<<1 | (sig128Z.v0 != 0);
132 goto roundPack;
133 }
134 normExpSig = softfloat_normSubnormalF64Sig( sigC );
135 expC = normExpSig.exp;
136 sigC = normExpSig.sig;
137 }
138 sigC = (sigC | UINT64_C( 0x0010000000000000 ))<<9;
139 /*------------------------------------------------------------------------
140 *------------------------------------------------------------------------*/
141 expDiff = expZ - expC;
142 if ( expDiff < 0 ) {
143 expZ = expC;
144 if ( (signZ == signC) || (expDiff < -1) ) {
145 sig128Z.v64 = softfloat_shiftRightJam64( sig128Z.v64, -expDiff );
146 } else {
147 sig128Z =
148 softfloat_shortShiftRightJam128( sig128Z.v64, sig128Z.v0, 1 );
149 }
150 } else if ( expDiff ) {
151 sig128C = softfloat_shiftRightJam128( sigC, 0, expDiff );
152 }
153 /*------------------------------------------------------------------------
154 *------------------------------------------------------------------------*/
155 if ( signZ == signC ) {
156 /*--------------------------------------------------------------------
157 *--------------------------------------------------------------------*/
158 if ( expDiff <= 0 ) {
159 sigZ = (sigC + sig128Z.v64) | (sig128Z.v0 != 0);
160 } else {
161 sig128Z =
162 softfloat_add128(
163 sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0 );
164 sigZ = sig128Z.v64 | (sig128Z.v0 != 0);
165 }
166 if ( sigZ < UINT64_C( 0x4000000000000000 ) ) {
167 --expZ;
168 sigZ <<= 1;
169 }
170 } else {
171 /*--------------------------------------------------------------------
172 *--------------------------------------------------------------------*/
173 if ( expDiff < 0 ) {
174 signZ = signC;
175 sig128Z = softfloat_sub128( sigC, 0, sig128Z.v64, sig128Z.v0 );
176 } else if ( ! expDiff ) {
177 sig128Z.v64 = sig128Z.v64 - sigC;
178 if ( ! (sig128Z.v64 | sig128Z.v0) ) goto completeCancellation;
179 if ( sig128Z.v64 & UINT64_C( 0x8000000000000000 ) ) {
180 signZ = ! signZ;
181 sig128Z = softfloat_sub128( 0, 0, sig128Z.v64, sig128Z.v0 );
182 }
183 } else {
184 sig128Z =
185 softfloat_sub128(
186 sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0 );
187 }
188 /*--------------------------------------------------------------------
189 *--------------------------------------------------------------------*/
190 if ( ! sig128Z.v64 ) {
191 expZ -= 64;
192 sig128Z.v64 = sig128Z.v0;
193 sig128Z.v0 = 0;
194 }
195 shiftDist = softfloat_countLeadingZeros64( sig128Z.v64 ) - 1;
196 expZ -= shiftDist;
197 if ( shiftDist < 0 ) {
198 sigZ = softfloat_shortShiftRightJam64( sig128Z.v64, -shiftDist );
199 } else {
200 sig128Z =
201 softfloat_shortShiftLeft128(
202 sig128Z.v64, sig128Z.v0, shiftDist );
203 sigZ = sig128Z.v64;
204 }
205 sigZ |= (sig128Z.v0 != 0);
206 }
207 roundPack:
208 return softfloat_roundPackToF64( signZ, expZ, sigZ );
209 /*------------------------------------------------------------------------
210 *------------------------------------------------------------------------*/
211 propagateNaN_ABC:
212 uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
213 goto propagateNaN_ZC;
214 /*------------------------------------------------------------------------
215 *------------------------------------------------------------------------*/
216 infProdArg:
217 if ( magBits ) {
218 uiZ = packToF64UI( signZ, 0x7FF, 0 );
219 if ( expC != 0x7FF ) goto uiZ;
220 if ( sigC ) goto propagateNaN_ZC;
221 if ( signZ == signC ) goto uiZ;
222 }
223 softfloat_raiseFlags( softfloat_flag_invalid );
224 uiZ = defaultNaNF64UI;
225 propagateNaN_ZC:
226 uiZ = softfloat_propagateNaNF64UI( uiZ, uiC );
227 goto uiZ;
228 /*------------------------------------------------------------------------
229 *------------------------------------------------------------------------*/
230 zeroProd:
231 uiZ = uiC;
232 if ( ! (expC | sigC) && (signZ != signC) ) {
233 completeCancellation:
234 uiZ =
235 packToF64UI(
236 (softfloat_roundingMode == softfloat_round_min), 0, 0 );
237 }
238 uiZ:
239 uZ.ui = uiZ;
240 return uZ.f;
241
242}
243
244#else
245
246float64_t
247 softfloat_mulAddF64(
248 uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC, uint_fast8_t op )
249{
250 bool signA;
251 int_fast16_t expA;
252 uint64_t sigA;
253 bool signB;
254 int_fast16_t expB;
255 uint64_t sigB;
256 bool signC;
257 int_fast16_t expC;
258 uint64_t sigC;
259 bool signZ;
260 uint64_t magBits, uiZ;
261 struct exp16_sig64 normExpSig;
262 int_fast16_t expZ;
263 uint32_t sig128Z[4];
264 uint64_t sigZ;
265 int_fast16_t shiftDist, expDiff;
266 uint32_t sig128C[4];
267 union ui64_f64 uZ;
268
269 /*------------------------------------------------------------------------
270 *------------------------------------------------------------------------*/
271 signA = signF64UI( uiA );
272 expA = expF64UI( uiA );
273 sigA = fracF64UI( uiA );
274 signB = signF64UI( uiB );
275 expB = expF64UI( uiB );
276 sigB = fracF64UI( uiB );
277 signC = signF64UI( uiC ) ^ (op == softfloat_mulAdd_subC);
278 expC = expF64UI( uiC );
279 sigC = fracF64UI( uiC );
280 signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd);
281 /*------------------------------------------------------------------------
282 *------------------------------------------------------------------------*/
283 if ( expA == 0x7FF ) {
284 if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN_ABC;
285 magBits = expB | sigB;
286 goto infProdArg;
287 }
288 if ( expB == 0x7FF ) {
289 if ( sigB ) goto propagateNaN_ABC;
290 magBits = expA | sigA;
291 goto infProdArg;
292 }
293 if ( expC == 0x7FF ) {
294 if ( sigC ) {
295 uiZ = 0;
296 goto propagateNaN_ZC;
297 }
298 uiZ = uiC;
299 goto uiZ;
300 }
301 /*------------------------------------------------------------------------
302 *------------------------------------------------------------------------*/
303 if ( ! expA ) {
304 if ( ! sigA ) goto zeroProd;
305 normExpSig = softfloat_normSubnormalF64Sig( sigA );
306 expA = normExpSig.exp;
307 sigA = normExpSig.sig;
308 }
309 if ( ! expB ) {
310 if ( ! sigB ) goto zeroProd;
311 normExpSig = softfloat_normSubnormalF64Sig( sigB );
312 expB = normExpSig.exp;
313 sigB = normExpSig.sig;
314 }
315 /*------------------------------------------------------------------------
316 *------------------------------------------------------------------------*/
317 expZ = expA + expB - 0x3FE;
318 sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10;
319 sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<11;
320 softfloat_mul64To128M( sigA, sigB, sig128Z );
321 sigZ =
322 (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )];
323 shiftDist = 0;
324 if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) {
325 --expZ;
326 shiftDist = -1;
327 }
328 if ( ! expC ) {
329 if ( ! sigC ) {
330 if ( shiftDist ) sigZ <<= 1;
331 goto sigZ;
332 }
333 normExpSig = softfloat_normSubnormalF64Sig( sigC );
334 expC = normExpSig.exp;
335 sigC = normExpSig.sig;
336 }
337 sigC = (sigC | UINT64_C( 0x0010000000000000 ))<<10;
338 /*------------------------------------------------------------------------
339 *------------------------------------------------------------------------*/
340 expDiff = expZ - expC;
341 if ( expDiff < 0 ) {
342 expZ = expC;
343 if ( (signZ == signC) || (expDiff < -1) ) {
344 shiftDist -= expDiff;
345 if ( shiftDist) {
346 sigZ = softfloat_shiftRightJam64( sigZ, shiftDist );
347 }
348 } else {
349 if ( ! shiftDist ) {
350 softfloat_shortShiftRight128M( sig128Z, 1, sig128Z );
351 }
352 }
353 } else {
354 if ( shiftDist ) softfloat_add128M( sig128Z, sig128Z, sig128Z );
355 if ( ! expDiff ) {
356 sigZ =
357 (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
358 | sig128Z[indexWord( 4, 2 )];
359 } else {
360 sig128C[indexWord( 4, 3 )] = sigC>>32;
361 sig128C[indexWord( 4, 2 )] = sigC;
362 sig128C[indexWord( 4, 1 )] = 0;
363 sig128C[indexWord( 4, 0 )] = 0;
364 softfloat_shiftRightJam128M( sig128C, expDiff, sig128C );
365 }
366 }
367 /*------------------------------------------------------------------------
368 *------------------------------------------------------------------------*/
369 if ( signZ == signC ) {
370 /*--------------------------------------------------------------------
371 *--------------------------------------------------------------------*/
372 if ( expDiff <= 0 ) {
373 sigZ += sigC;
374 } else {
375 softfloat_add128M( sig128Z, sig128C, sig128Z );
376 sigZ =
377 (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
378 | sig128Z[indexWord( 4, 2 )];
379 }
380 if ( sigZ & UINT64_C( 0x8000000000000000 ) ) {
381 ++expZ;
382 sigZ = softfloat_shortShiftRightJam64( sigZ, 1 );
383 }
384 } else {
385 /*--------------------------------------------------------------------
386 *--------------------------------------------------------------------*/
387 if ( expDiff < 0 ) {
388 signZ = signC;
389 if ( expDiff < -1 ) {
390 sigZ = sigC - sigZ;
391 if (
392 sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )]
393 ) {
394 sigZ = (sigZ - 1) | 1;
395 }
396 if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) {
397 --expZ;
398 sigZ <<= 1;
399 }
400 goto roundPack;
401 } else {
402 sig128C[indexWord( 4, 3 )] = sigC>>32;
403 sig128C[indexWord( 4, 2 )] = sigC;
404 sig128C[indexWord( 4, 1 )] = 0;
405 sig128C[indexWord( 4, 0 )] = 0;
406 softfloat_sub128M( sig128C, sig128Z, sig128Z );
407 }
408 } else if ( ! expDiff ) {
409 sigZ -= sigC;
410 if (
411 ! sigZ && ! sig128Z[indexWord( 4, 1 )]
412 && ! sig128Z[indexWord( 4, 0 )]
413 ) {
414 goto completeCancellation;
415 }
416 sig128Z[indexWord( 4, 3 )] = sigZ>>32;
417 sig128Z[indexWord( 4, 2 )] = sigZ;
418 if ( sigZ & UINT64_C( 0x8000000000000000 ) ) {
419 signZ = ! signZ;
420 softfloat_negX128M( sig128Z );
421 }
422 } else {
423 softfloat_sub128M( sig128Z, sig128C, sig128Z );
424 if ( 1 < expDiff ) {
425 sigZ =
426 (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
427 | sig128Z[indexWord( 4, 2 )];
428 if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) {
429 --expZ;
430 sigZ <<= 1;
431 }
432 goto sigZ;
433 }
434 }
435 /*--------------------------------------------------------------------
436 *--------------------------------------------------------------------*/
437 shiftDist = 0;
438 sigZ =
439 (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
440 | sig128Z[indexWord( 4, 2 )];
441 if ( ! sigZ ) {
442 shiftDist = 64;
443 sigZ =
444 (uint64_t) sig128Z[indexWord( 4, 1 )]<<32
445 | sig128Z[indexWord( 4, 0 )];
446 }
447 shiftDist += softfloat_countLeadingZeros64( sigZ ) - 1;
448 if ( shiftDist ) {
449 expZ -= shiftDist;
450 softfloat_shiftLeft128M( sig128Z, shiftDist, sig128Z );
451 sigZ =
452 (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
453 | sig128Z[indexWord( 4, 2 )];
454 }
455 }
456 sigZ:
457 if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) sigZ |= 1;
458 roundPack:
459 return softfloat_roundPackToF64( signZ, expZ - 1, sigZ );
460 /*------------------------------------------------------------------------
461 *------------------------------------------------------------------------*/
462 propagateNaN_ABC:
463 uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
464 goto propagateNaN_ZC;
465 /*------------------------------------------------------------------------
466 *------------------------------------------------------------------------*/
467 infProdArg:
468 if ( magBits ) {
469 uiZ = packToF64UI( signZ, 0x7FF, 0 );
470 if ( expC != 0x7FF ) goto uiZ;
471 if ( sigC ) goto propagateNaN_ZC;
472 if ( signZ == signC ) goto uiZ;
473 }
474 softfloat_raiseFlags( softfloat_flag_invalid );
475 uiZ = defaultNaNF64UI;
476 propagateNaN_ZC:
477 uiZ = softfloat_propagateNaNF64UI( uiZ, uiC );
478 goto uiZ;
479 /*------------------------------------------------------------------------
480 *------------------------------------------------------------------------*/
481 zeroProd:
482 uiZ = uiC;
483 if ( ! (expC | sigC) && (signZ != signC) ) {
484 completeCancellation:
485 uiZ =
486 packToF64UI(
487 (softfloat_roundingMode == softfloat_round_min), 0, 0 );
488 }
489 uiZ:
490 uZ.ui = uiZ;
491 return uZ.f;
492
493}
494
495#endif
496
deps/SoftFloat-3e/source/s_negXM.c deleted-63
...@@ -1,63 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_negXM
42
43void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr )
44{
45 unsigned int index, lastIndex;
46 uint_fast8_t carry;
47 uint32_t word;
48
49 index = indexWordLo( size_words );
50 lastIndex = indexWordHi( size_words );
51 carry = 1;
52 for (;;) {
53 word = ~zPtr[index] + carry;
54 zPtr[index] = word;
55 if ( index == lastIndex ) break;
56 index += wordIncr;
57 if ( word ) carry = 0;
58 }
59
60}
61
62#endif
63
deps/SoftFloat-3e/source/s_normExtF80SigM.c deleted-52
...@@ -1,52 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40
41int softfloat_normExtF80SigM( uint64_t *sigPtr )
42{
43 uint64_t sig;
44 int_fast8_t shiftDist;
45
46 sig = *sigPtr;
47 shiftDist = softfloat_countLeadingZeros64( sig );
48 *sigPtr = sig<<shiftDist;
49 return -shiftDist;
50
51}
52
deps/SoftFloat-3e/source/s_normRoundPackMToExtF80M.c deleted-78
...@@ -1,78 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41
42void
43 softfloat_normRoundPackMToExtF80M(
44 bool sign,
45 int32_t exp,
46 uint32_t *extSigPtr,
47 uint_fast8_t roundingPrecision,
48 struct extFloat80M *zSPtr
49 )
50{
51 int_fast16_t shiftDist;
52 uint32_t wordSig;
53
54 shiftDist = 0;
55 wordSig = extSigPtr[indexWord( 3, 2 )];
56 if ( ! wordSig ) {
57 shiftDist = 32;
58 wordSig = extSigPtr[indexWord( 3, 1 )];
59 if ( ! wordSig ) {
60 shiftDist = 64;
61 wordSig = extSigPtr[indexWord( 3, 0 )];
62 if ( ! wordSig ) {
63 zSPtr->signExp = packToExtF80UI64( sign, 0 );
64 zSPtr->signif = 0;
65 return;
66 }
67 }
68 }
69 shiftDist += softfloat_countLeadingZeros32( wordSig );
70 if ( shiftDist ) {
71 exp -= shiftDist;
72 softfloat_shiftLeft96M( extSigPtr, shiftDist, extSigPtr );
73 }
74 softfloat_roundPackMToExtF80M(
75 sign, exp, extSigPtr, roundingPrecision, zSPtr );
76
77}
78
deps/SoftFloat-3e/source/s_normRoundPackMToF128M.c deleted-73
...@@ -1,73 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41
42void
43 softfloat_normRoundPackMToF128M(
44 bool sign, int32_t exp, uint32_t *extSigPtr, uint32_t *zWPtr )
45{
46 const uint32_t *ptr;
47 int_fast16_t shiftDist;
48 uint32_t wordSig;
49
50 ptr = extSigPtr + indexWordHi( 5 );
51 shiftDist = 0;
52 for (;;) {
53 wordSig = *ptr;
54 if ( wordSig ) break;
55 shiftDist += 32;
56 if ( 160 <= shiftDist ) {
57 zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, 0, 0 );
58 zWPtr[indexWord( 4, 2 )] = 0;
59 zWPtr[indexWord( 4, 1 )] = 0;
60 zWPtr[indexWord( 4, 0 )] = 0;
61 return;
62 }
63 ptr -= wordIncr;
64 }
65 shiftDist += softfloat_countLeadingZeros32( wordSig ) - 15;
66 if ( shiftDist ) {
67 exp -= shiftDist;
68 softfloat_shiftLeft160M( extSigPtr, shiftDist, extSigPtr );
69 }
70 softfloat_roundPackMToF128M( sign, exp, extSigPtr, zWPtr );
71
72}
73
deps/SoftFloat-3e/source/s_normRoundPackToExtF80.c deleted-71
...@@ -1,71 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41
42extFloat80_t
43 softfloat_normRoundPackToExtF80(
44 bool sign,
45 int_fast32_t exp,
46 uint_fast64_t sig,
47 uint_fast64_t sigExtra,
48 uint_fast8_t roundingPrecision
49 )
50{
51 int_fast8_t shiftDist;
52 struct uint128 sig128;
53
54 if ( ! sig ) {
55 exp -= 64;
56 sig = sigExtra;
57 sigExtra = 0;
58 }
59 shiftDist = softfloat_countLeadingZeros64( sig );
60 exp -= shiftDist;
61 if ( shiftDist ) {
62 sig128 = softfloat_shortShiftLeft128( sig, sigExtra, shiftDist );
63 sig = sig128.v64;
64 sigExtra = sig128.v0;
65 }
66 return
67 softfloat_roundPackToExtF80(
68 sign, exp, sig, sigExtra, roundingPrecision );
69
70}
71
deps/SoftFloat-3e/source/s_normRoundPackToF128.c deleted-81
...@@ -1,81 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41
42float128_t
43 softfloat_normRoundPackToF128(
44 bool sign, int_fast32_t exp, uint_fast64_t sig64, uint_fast64_t sig0 )
45{
46 int_fast8_t shiftDist;
47 struct uint128 sig128;
48 union ui128_f128 uZ;
49 uint_fast64_t sigExtra;
50 struct uint128_extra sig128Extra;
51
52 if ( ! sig64 ) {
53 exp -= 64;
54 sig64 = sig0;
55 sig0 = 0;
56 }
57 shiftDist = softfloat_countLeadingZeros64( sig64 ) - 15;
58 exp -= shiftDist;
59 if ( 0 <= shiftDist ) {
60 if ( shiftDist ) {
61 sig128 = softfloat_shortShiftLeft128( sig64, sig0, shiftDist );
62 sig64 = sig128.v64;
63 sig0 = sig128.v0;
64 }
65 if ( (uint32_t) exp < 0x7FFD ) {
66 uZ.ui.v64 = packToF128UI64( sign, sig64 | sig0 ? exp : 0, sig64 );
67 uZ.ui.v0 = sig0;
68 return uZ.f;
69 }
70 sigExtra = 0;
71 } else {
72 sig128Extra =
73 softfloat_shortShiftRightJam128Extra( sig64, sig0, 0, -shiftDist );
74 sig64 = sig128Extra.v.v64;
75 sig0 = sig128Extra.v.v0;
76 sigExtra = sig128Extra.extra;
77 }
78 return softfloat_roundPackToF128( sign, exp, sig64, sig0, sigExtra );
79
80}
81
deps/SoftFloat-3e/source/s_normRoundPackToF16.c deleted-58
...@@ -1,58 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41
42float16_t
43 softfloat_normRoundPackToF16( bool sign, int_fast16_t exp, uint_fast16_t sig )
44{
45 int_fast8_t shiftDist;
46 union ui16_f16 uZ;
47
48 shiftDist = softfloat_countLeadingZeros16( sig ) - 1;
49 exp -= shiftDist;
50 if ( (4 <= shiftDist) && ((unsigned int) exp < 0x1D) ) {
51 uZ.ui = packToF16UI( sign, sig ? exp : 0, sig<<(shiftDist - 4) );
52 return uZ.f;
53 } else {
54 return softfloat_roundPackToF16( sign, exp, sig<<shiftDist );
55 }
56
57}
58
deps/SoftFloat-3e/source/s_normRoundPackToF32.c deleted-58
...@@ -1,58 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41
42float32_t
43 softfloat_normRoundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig )
44{
45 int_fast8_t shiftDist;
46 union ui32_f32 uZ;
47
48 shiftDist = softfloat_countLeadingZeros32( sig ) - 1;
49 exp -= shiftDist;
50 if ( (7 <= shiftDist) && ((unsigned int) exp < 0xFD) ) {
51 uZ.ui = packToF32UI( sign, sig ? exp : 0, sig<<(shiftDist - 7) );
52 return uZ.f;
53 } else {
54 return softfloat_roundPackToF32( sign, exp, sig<<shiftDist );
55 }
56
57}
58
deps/SoftFloat-3e/source/s_normRoundPackToF64.c deleted-58
...@@ -1,58 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41
42float64_t
43 softfloat_normRoundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig )
44{
45 int_fast8_t shiftDist;
46 union ui64_f64 uZ;
47
48 shiftDist = softfloat_countLeadingZeros64( sig ) - 1;
49 exp -= shiftDist;
50 if ( (10 <= shiftDist) && ((unsigned int) exp < 0x7FD) ) {
51 uZ.ui = packToF64UI( sign, sig ? exp : 0, sig<<(shiftDist - 10) );
52 return uZ.f;
53 } else {
54 return softfloat_roundPackToF64( sign, exp, sig<<shiftDist );
55 }
56
57}
58
deps/SoftFloat-3e/source/s_normSubnormalExtF80Sig.c deleted-52
...@@ -1,52 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40
41struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t sig )
42{
43 int_fast8_t shiftDist;
44 struct exp32_sig64 z;
45
46 shiftDist = softfloat_countLeadingZeros64( sig );
47 z.exp = -shiftDist;
48 z.sig = sig<<shiftDist;
49 return z;
50
51}
52
deps/SoftFloat-3e/source/s_normSubnormalF128Sig.c deleted-65
...@@ -1,65 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40
41struct exp32_sig128
42 softfloat_normSubnormalF128Sig( uint_fast64_t sig64, uint_fast64_t sig0 )
43{
44 int_fast8_t shiftDist;
45 struct exp32_sig128 z;
46
47 if ( ! sig64 ) {
48 shiftDist = softfloat_countLeadingZeros64( sig0 ) - 15;
49 z.exp = -63 - shiftDist;
50 if ( shiftDist < 0 ) {
51 z.sig.v64 = sig0>>-shiftDist;
52 z.sig.v0 = sig0<<(shiftDist & 63);
53 } else {
54 z.sig.v64 = sig0<<shiftDist;
55 z.sig.v0 = 0;
56 }
57 } else {
58 shiftDist = softfloat_countLeadingZeros64( sig64 ) - 15;
59 z.exp = 1 - shiftDist;
60 z.sig = softfloat_shortShiftLeft128( sig64, sig0, shiftDist );
61 }
62 return z;
63
64}
65
deps/SoftFloat-3e/source/s_normSubnormalF128SigM.c deleted-61
...@@ -1,61 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40
41int softfloat_normSubnormalF128SigM( uint32_t *sigPtr )
42{
43 const uint32_t *ptr;
44 int_fast16_t shiftDist;
45 uint32_t wordSig;
46
47 ptr = sigPtr + indexWordHi( 4 );
48 shiftDist = 0;
49 for (;;) {
50 wordSig = *ptr;
51 if ( wordSig ) break;
52 shiftDist += 32;
53 if ( 128 <= shiftDist ) return 1;
54 ptr -= wordIncr;
55 }
56 shiftDist += softfloat_countLeadingZeros32( wordSig ) - 15;
57 if ( shiftDist ) softfloat_shiftLeft128M( sigPtr, shiftDist, sigPtr );
58 return 1 - shiftDist;
59
60}
61
deps/SoftFloat-3e/source/s_normSubnormalF16Sig.c deleted-52
...@@ -1,52 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40
41struct exp8_sig16 softfloat_normSubnormalF16Sig( uint_fast16_t sig )
42{
43 int_fast8_t shiftDist;
44 struct exp8_sig16 z;
45
46 shiftDist = softfloat_countLeadingZeros16( sig ) - 5;
47 z.exp = 1 - shiftDist;
48 z.sig = sig<<shiftDist;
49 return z;
50
51}
52
deps/SoftFloat-3e/source/s_normSubnormalF32Sig.c deleted-52
...@@ -1,52 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40
41struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t sig )
42{
43 int_fast8_t shiftDist;
44 struct exp16_sig32 z;
45
46 shiftDist = softfloat_countLeadingZeros32( sig ) - 8;
47 z.exp = 1 - shiftDist;
48 z.sig = sig<<shiftDist;
49 return z;
50
51}
52
deps/SoftFloat-3e/source/s_normSubnormalF64Sig.c deleted-52
...@@ -1,52 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40
41struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t sig )
42{
43 int_fast8_t shiftDist;
44 struct exp16_sig64 z;
45
46 shiftDist = softfloat_countLeadingZeros64( sig ) - 11;
47 z.exp = 1 - shiftDist;
48 z.sig = sig<<shiftDist;
49 return z;
50
51}
52
deps/SoftFloat-3e/source/s_remStepMBy32.c deleted-86
...@@ -1,86 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_remStepMBy32
42
43void
44 softfloat_remStepMBy32(
45 uint_fast8_t size_words,
46 const uint32_t *remPtr,
47 uint_fast8_t dist,
48 const uint32_t *bPtr,
49 uint32_t q,
50 uint32_t *zPtr
51 )
52{
53 unsigned int index, lastIndex;
54 uint64_t dwordProd;
55 uint32_t wordRem, wordShiftedRem, wordProd;
56 uint_fast8_t uNegDist, borrow;
57
58 index = indexWordLo( size_words );
59 lastIndex = indexWordHi( size_words );
60 dwordProd = (uint64_t) bPtr[index] * q;
61 wordRem = remPtr[index];
62 wordShiftedRem = wordRem<<dist;
63 wordProd = dwordProd;
64 zPtr[index] = wordShiftedRem - wordProd;
65 if ( index != lastIndex ) {
66 uNegDist = -dist;
67 borrow = (wordShiftedRem < wordProd);
68 for (;;) {
69 wordShiftedRem = wordRem>>(uNegDist & 31);
70 index += wordIncr;
71 dwordProd = (uint64_t) bPtr[index] * q + (dwordProd>>32);
72 wordRem = remPtr[index];
73 wordShiftedRem |= wordRem<<dist;
74 wordProd = dwordProd;
75 zPtr[index] = wordShiftedRem - wordProd - borrow;
76 if ( index == lastIndex ) break;
77 borrow =
78 borrow ? (wordShiftedRem <= wordProd)
79 : (wordShiftedRem < wordProd);
80 }
81 }
82
83}
84
85#endif
86
deps/SoftFloat-3e/source/s_roundMToI64.c deleted-102
...@@ -1,102 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast64_t
45 softfloat_roundMToI64(
46 bool sign, uint32_t *extSigPtr, uint_fast8_t roundingMode, bool exact )
47{
48 uint64_t sig;
49 uint32_t sigExtra;
50 union { uint64_t ui; int64_t i; } uZ;
51 int64_t z;
52
53 /*------------------------------------------------------------------------
54 *------------------------------------------------------------------------*/
55 sig =
56 (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32
57 | extSigPtr[indexWord( 3, 1 )];
58 sigExtra = extSigPtr[indexWordLo( 3 )];
59 if (
60 (roundingMode == softfloat_round_near_maxMag)
61 || (roundingMode == softfloat_round_near_even)
62 ) {
63 if ( 0x80000000 <= sigExtra ) goto increment;
64 } else {
65 if (
66 sigExtra
67 && (sign
68 ? (roundingMode == softfloat_round_min)
69#ifdef SOFTFLOAT_ROUND_ODD
70 || (roundingMode == softfloat_round_odd)
71#endif
72 : (roundingMode == softfloat_round_max))
73 ) {
74 increment:
75 ++sig;
76 if ( !sig ) goto invalid;
77 if (
78 (sigExtra == 0x80000000)
79 && (roundingMode == softfloat_round_near_even)
80 ) {
81 sig &= ~(uint_fast64_t) 1;
82 }
83 }
84 }
85 uZ.ui = sign ? -sig : sig;
86 z = uZ.i;
87 if ( z && ((z < 0) ^ sign) ) goto invalid;
88 if ( sigExtra ) {
89#ifdef SOFTFLOAT_ROUND_ODD
90 if ( roundingMode == softfloat_round_odd ) z |= 1;
91#endif
92 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
93 }
94 return z;
95 /*------------------------------------------------------------------------
96 *------------------------------------------------------------------------*/
97 invalid:
98 softfloat_raiseFlags( softfloat_flag_invalid );
99 return sign ? i64_fromNegOverflow : i64_fromPosOverflow;
100
101}
102
deps/SoftFloat-3e/source/s_roundMToUI64.c deleted-98
...@@ -1,98 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast64_t
45 softfloat_roundMToUI64(
46 bool sign, uint32_t *extSigPtr, uint_fast8_t roundingMode, bool exact )
47{
48 uint64_t sig;
49 uint32_t sigExtra;
50
51 /*------------------------------------------------------------------------
52 *------------------------------------------------------------------------*/
53 sig =
54 (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32
55 | extSigPtr[indexWord( 3, 1 )];
56 sigExtra = extSigPtr[indexWordLo( 3 )];
57 if (
58 (roundingMode == softfloat_round_near_maxMag)
59 || (roundingMode == softfloat_round_near_even)
60 ) {
61 if ( 0x80000000 <= sigExtra ) goto increment;
62 } else {
63 if ( sign ) {
64 if ( !(sig | sigExtra) ) return 0;
65 if ( roundingMode == softfloat_round_min ) goto invalid;
66#ifdef SOFTFLOAT_ROUND_ODD
67 if ( roundingMode == softfloat_round_odd ) goto invalid;
68#endif
69 } else {
70 if ( (roundingMode == softfloat_round_max) && sigExtra ) {
71 increment:
72 ++sig;
73 if ( !sig ) goto invalid;
74 if (
75 (sigExtra == 0x80000000)
76 && (roundingMode == softfloat_round_near_even)
77 ) {
78 sig &= ~(uint_fast64_t) 1;
79 }
80 }
81 }
82 }
83 if ( sign && sig ) goto invalid;
84 if ( sigExtra ) {
85#ifdef SOFTFLOAT_ROUND_ODD
86 if ( roundingMode == softfloat_round_odd ) sig |= 1;
87#endif
88 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
89 }
90 return sig;
91 /*------------------------------------------------------------------------
92 *------------------------------------------------------------------------*/
93 invalid:
94 softfloat_raiseFlags( softfloat_flag_invalid );
95 return sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
96
97}
98
deps/SoftFloat-3e/source/s_roundPackMToExtF80M.c deleted-256
...@@ -1,256 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43void
44 softfloat_roundPackMToExtF80M(
45 bool sign,
46 int32_t exp,
47 uint32_t *extSigPtr,
48 uint_fast8_t roundingPrecision,
49 struct extFloat80M *zSPtr
50 )
51{
52 uint_fast8_t roundingMode;
53 bool roundNearEven;
54 uint64_t sig, roundIncrement, roundMask, roundBits;
55 bool isTiny;
56 uint32_t sigExtra;
57 bool doIncrement;
58
59 /*------------------------------------------------------------------------
60 *------------------------------------------------------------------------*/
61 roundingMode = softfloat_roundingMode;
62 roundNearEven = (roundingMode == softfloat_round_near_even);
63 sig =
64 (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32
65 | extSigPtr[indexWord( 3, 1 )];
66 if ( roundingPrecision == 80 ) goto precision80;
67 if ( roundingPrecision == 64 ) {
68 roundIncrement = UINT64_C( 0x0000000000000400 );
69 roundMask = UINT64_C( 0x00000000000007FF );
70 } else if ( roundingPrecision == 32 ) {
71 roundIncrement = UINT64_C( 0x0000008000000000 );
72 roundMask = UINT64_C( 0x000000FFFFFFFFFF );
73 } else {
74 goto precision80;
75 }
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 if ( extSigPtr[indexWordLo( 3 )] ) sig |= 1;
79 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
80 roundIncrement =
81 (roundingMode
82 == (sign ? softfloat_round_min : softfloat_round_max))
83 ? roundMask
84 : 0;
85 }
86 roundBits = sig & roundMask;
87 /*------------------------------------------------------------------------
88 *------------------------------------------------------------------------*/
89 if ( 0x7FFD <= (uint32_t) (exp - 1) ) {
90 if ( exp <= 0 ) {
91 /*----------------------------------------------------------------
92 *----------------------------------------------------------------*/
93 isTiny =
94 (softfloat_detectTininess
95 == softfloat_tininess_beforeRounding)
96 || (exp < 0)
97 || (sig <= (uint64_t) (sig + roundIncrement));
98 sig = softfloat_shiftRightJam64( sig, 1 - exp );
99 roundBits = sig & roundMask;
100 if ( roundBits ) {
101 if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow );
102 softfloat_exceptionFlags |= softfloat_flag_inexact;
103#ifdef SOFTFLOAT_ROUND_ODD
104 if ( roundingMode == softfloat_round_odd ) {
105 sig |= roundMask + 1;
106 }
107#endif
108 }
109 sig += roundIncrement;
110 exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
111 roundIncrement = roundMask + 1;
112 if ( roundNearEven && (roundBits<<1 == roundIncrement) ) {
113 roundMask |= roundIncrement;
114 }
115 sig &= ~roundMask;
116 goto packReturn;
117 }
118 if (
119 (0x7FFE < exp)
120 || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig))
121 ) {
122 goto overflow;
123 }
124 }
125 /*------------------------------------------------------------------------
126 *------------------------------------------------------------------------*/
127 if ( roundBits ) {
128 softfloat_exceptionFlags |= softfloat_flag_inexact;
129#ifdef SOFTFLOAT_ROUND_ODD
130 if ( roundingMode == softfloat_round_odd ) {
131 sig = (sig & ~roundMask) | (roundMask + 1);
132 goto packReturn;
133 }
134#endif
135 }
136 sig += roundIncrement;
137 if ( sig < roundIncrement ) {
138 ++exp;
139 sig = UINT64_C( 0x8000000000000000 );
140 }
141 roundIncrement = roundMask + 1;
142 if ( roundNearEven && (roundBits<<1 == roundIncrement) ) {
143 roundMask |= roundIncrement;
144 }
145 sig &= ~roundMask;
146 goto packReturn;
147 /*------------------------------------------------------------------------
148 *------------------------------------------------------------------------*/
149 precision80:
150 sigExtra = extSigPtr[indexWordLo( 3 )];
151 doIncrement = (0x80000000 <= sigExtra);
152 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
153 doIncrement =
154 (roundingMode
155 == (sign ? softfloat_round_min : softfloat_round_max))
156 && sigExtra;
157 }
158 /*------------------------------------------------------------------------
159 *------------------------------------------------------------------------*/
160 if ( 0x7FFD <= (uint32_t) (exp - 1) ) {
161 if ( exp <= 0 ) {
162 /*----------------------------------------------------------------
163 *----------------------------------------------------------------*/
164 isTiny =
165 (softfloat_detectTininess
166 == softfloat_tininess_beforeRounding)
167 || (exp < 0)
168 || ! doIncrement
169 || (sig < UINT64_C( 0xFFFFFFFFFFFFFFFF ));
170 softfloat_shiftRightJam96M( extSigPtr, 1 - exp, extSigPtr );
171 exp = 0;
172 sig =
173 (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32
174 | extSigPtr[indexWord( 3, 1 )];
175 sigExtra = extSigPtr[indexWordLo( 3 )];
176 if ( sigExtra ) {
177 if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow );
178 softfloat_exceptionFlags |= softfloat_flag_inexact;
179#ifdef SOFTFLOAT_ROUND_ODD
180 if ( roundingMode == softfloat_round_odd ) {
181 sig |= 1;
182 goto packReturn;
183 }
184#endif
185 }
186 doIncrement = (0x80000000 <= sigExtra);
187 if (
188 ! roundNearEven
189 && (roundingMode != softfloat_round_near_maxMag)
190 ) {
191 doIncrement =
192 (roundingMode
193 == (sign ? softfloat_round_min : softfloat_round_max))
194 && sigExtra;
195 }
196 if ( doIncrement ) {
197 ++sig;
198 sig &= ~(uint64_t) (! (sigExtra & 0x7FFFFFFF) & roundNearEven);
199 exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
200 }
201 goto packReturn;
202 }
203 if (
204 (0x7FFE < exp)
205 || ((exp == 0x7FFE) && (sig == UINT64_C( 0xFFFFFFFFFFFFFFFF ))
206 && doIncrement)
207 ) {
208 /*----------------------------------------------------------------
209 *----------------------------------------------------------------*/
210 roundMask = 0;
211 overflow:
212 softfloat_raiseFlags(
213 softfloat_flag_overflow | softfloat_flag_inexact );
214 if (
215 roundNearEven
216 || (roundingMode == softfloat_round_near_maxMag)
217 || (roundingMode
218 == (sign ? softfloat_round_min : softfloat_round_max))
219 ) {
220 exp = 0x7FFF;
221 sig = UINT64_C( 0x8000000000000000 );
222 } else {
223 exp = 0x7FFE;
224 sig = ~roundMask;
225 }
226 goto packReturn;
227 }
228 }
229 /*------------------------------------------------------------------------
230 *------------------------------------------------------------------------*/
231 if ( sigExtra ) {
232 softfloat_exceptionFlags |= softfloat_flag_inexact;
233#ifdef SOFTFLOAT_ROUND_ODD
234 if ( roundingMode == softfloat_round_odd ) {
235 sig |= 1;
236 goto packReturn;
237 }
238#endif
239 }
240 if ( doIncrement ) {
241 ++sig;
242 if ( ! sig ) {
243 ++exp;
244 sig = UINT64_C( 0x8000000000000000 );
245 } else {
246 sig &= ~(uint64_t) (! (sigExtra & 0x7FFFFFFF) & roundNearEven);
247 }
248 }
249 /*------------------------------------------------------------------------
250 *------------------------------------------------------------------------*/
251 packReturn:
252 zSPtr->signExp = packToExtF80UI64( sign, exp );
253 zSPtr->signif = sig;
254
255}
256
deps/SoftFloat-3e/source/s_roundPackMToF128M.c deleted-178
...@@ -1,178 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43void
44 softfloat_roundPackMToF128M(
45 bool sign, int32_t exp, uint32_t *extSigPtr, uint32_t *zWPtr )
46{
47 uint_fast8_t roundingMode;
48 bool roundNearEven;
49 uint32_t sigExtra;
50 bool doIncrement, isTiny;
51 static const uint32_t maxSig[4] =
52 INIT_UINTM4( 0x0001FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF );
53 uint32_t ui, uj;
54
55 /*------------------------------------------------------------------------
56 *------------------------------------------------------------------------*/
57 roundingMode = softfloat_roundingMode;
58 roundNearEven = (roundingMode == softfloat_round_near_even);
59 sigExtra = extSigPtr[indexWordLo( 5 )];
60 doIncrement = (0x80000000 <= sigExtra);
61 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
62 doIncrement =
63 (roundingMode
64 == (sign ? softfloat_round_min : softfloat_round_max))
65 && sigExtra;
66 }
67 /*------------------------------------------------------------------------
68 *------------------------------------------------------------------------*/
69 if ( 0x7FFD <= (uint32_t) exp ) {
70 if ( exp < 0 ) {
71 /*----------------------------------------------------------------
72 *----------------------------------------------------------------*/
73 isTiny =
74 (softfloat_detectTininess
75 == softfloat_tininess_beforeRounding)
76 || (exp < -1)
77 || ! doIncrement
78 || (softfloat_compare128M(
79 extSigPtr + indexMultiwordHi( 5, 4 ), maxSig )
80 < 0);
81 softfloat_shiftRightJam160M( extSigPtr, -exp, extSigPtr );
82 exp = 0;
83 sigExtra = extSigPtr[indexWordLo( 5 )];
84 if ( isTiny && sigExtra ) {
85 softfloat_raiseFlags( softfloat_flag_underflow );
86 }
87 doIncrement = (0x80000000 <= sigExtra);
88 if (
89 ! roundNearEven
90 && (roundingMode != softfloat_round_near_maxMag)
91 ) {
92 doIncrement =
93 (roundingMode
94 == (sign ? softfloat_round_min : softfloat_round_max))
95 && sigExtra;
96 }
97 } else if (
98 (0x7FFD < exp)
99 || ((exp == 0x7FFD) && doIncrement
100 && (softfloat_compare128M(
101 extSigPtr + indexMultiwordHi( 5, 4 ), maxSig )
102 == 0))
103 ) {
104 /*----------------------------------------------------------------
105 *----------------------------------------------------------------*/
106 softfloat_raiseFlags(
107 softfloat_flag_overflow | softfloat_flag_inexact );
108 if (
109 roundNearEven
110 || (roundingMode == softfloat_round_near_maxMag)
111 || (roundingMode
112 == (sign ? softfloat_round_min : softfloat_round_max))
113 ) {
114 ui = packToF128UI96( sign, 0x7FFF, 0 );
115 uj = 0;
116 } else {
117 ui = packToF128UI96( sign, 0x7FFE, 0x0000FFFF );
118 uj = 0xFFFFFFFF;
119 }
120 zWPtr[indexWordHi( 4 )] = ui;
121 zWPtr[indexWord( 4, 2 )] = uj;
122 zWPtr[indexWord( 4, 1 )] = uj;
123 zWPtr[indexWord( 4, 0 )] = uj;
124 return;
125 }
126 }
127 /*------------------------------------------------------------------------
128 *------------------------------------------------------------------------*/
129 uj = extSigPtr[indexWord( 5, 1 )];
130 if ( sigExtra ) {
131 softfloat_exceptionFlags |= softfloat_flag_inexact;
132#ifdef SOFTFLOAT_ROUND_ODD
133 if ( roundingMode == softfloat_round_odd ) {
134 uj |= 1;
135 goto noIncrementPackReturn;
136 }
137#endif
138 }
139 if ( doIncrement ) {
140 ++uj;
141 if ( uj ) {
142 if ( ! (sigExtra & 0x7FFFFFFF) && roundNearEven ) uj &= ~1;
143 zWPtr[indexWord( 4, 2 )] = extSigPtr[indexWord( 5, 3 )];
144 zWPtr[indexWord( 4, 1 )] = extSigPtr[indexWord( 5, 2 )];
145 zWPtr[indexWord( 4, 0 )] = uj;
146 ui = extSigPtr[indexWordHi( 5 )];
147 } else {
148 zWPtr[indexWord( 4, 0 )] = uj;
149 ui = extSigPtr[indexWord( 5, 2 )] + 1;
150 zWPtr[indexWord( 4, 1 )] = ui;
151 uj = extSigPtr[indexWord( 5, 3 )];
152 if ( ui ) {
153 zWPtr[indexWord( 4, 2 )] = uj;
154 ui = extSigPtr[indexWordHi( 5 )];
155 } else {
156 ++uj;
157 zWPtr[indexWord( 4, 2 )] = uj;
158 ui = extSigPtr[indexWordHi( 5 )];
159 if ( ! uj ) ++ui;
160 }
161 }
162 } else {
163 noIncrementPackReturn:
164 zWPtr[indexWord( 4, 0 )] = uj;
165 ui = extSigPtr[indexWord( 5, 2 )];
166 zWPtr[indexWord( 4, 1 )] = ui;
167 uj |= ui;
168 ui = extSigPtr[indexWord( 5, 3 )];
169 zWPtr[indexWord( 4, 2 )] = ui;
170 uj |= ui;
171 ui = extSigPtr[indexWordHi( 5 )];
172 uj |= ui;
173 if ( ! uj ) exp = 0;
174 }
175 zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, exp, ui );
176
177}
178
deps/SoftFloat-3e/source/s_roundPackToExtF80.c deleted-256
...@@ -1,256 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43extFloat80_t
44 softfloat_roundPackToExtF80(
45 bool sign,
46 int_fast32_t exp,
47 uint_fast64_t sig,
48 uint_fast64_t sigExtra,
49 uint_fast8_t roundingPrecision
50 )
51{
52 uint_fast8_t roundingMode;
53 bool roundNearEven;
54 uint_fast64_t roundIncrement, roundMask, roundBits;
55 bool isTiny, doIncrement;
56 struct uint64_extra sig64Extra;
57 union { struct extFloat80M s; extFloat80_t f; } uZ;
58
59 /*------------------------------------------------------------------------
60 *------------------------------------------------------------------------*/
61 roundingMode = softfloat_roundingMode;
62 roundNearEven = (roundingMode == softfloat_round_near_even);
63 if ( roundingPrecision == 80 ) goto precision80;
64 if ( roundingPrecision == 64 ) {
65 roundIncrement = UINT64_C( 0x0000000000000400 );
66 roundMask = UINT64_C( 0x00000000000007FF );
67 } else if ( roundingPrecision == 32 ) {
68 roundIncrement = UINT64_C( 0x0000008000000000 );
69 roundMask = UINT64_C( 0x000000FFFFFFFFFF );
70 } else {
71 goto precision80;
72 }
73 sig |= (sigExtra != 0);
74 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
75 roundIncrement =
76 (roundingMode
77 == (sign ? softfloat_round_min : softfloat_round_max))
78 ? roundMask
79 : 0;
80 }
81 roundBits = sig & roundMask;
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( 0x7FFD <= (uint32_t) (exp - 1) ) {
85 if ( exp <= 0 ) {
86 /*----------------------------------------------------------------
87 *----------------------------------------------------------------*/
88 isTiny =
89 (softfloat_detectTininess
90 == softfloat_tininess_beforeRounding)
91 || (exp < 0)
92 || (sig <= (uint64_t) (sig + roundIncrement));
93 sig = softfloat_shiftRightJam64( sig, 1 - exp );
94 roundBits = sig & roundMask;
95 if ( roundBits ) {
96 if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow );
97 softfloat_exceptionFlags |= softfloat_flag_inexact;
98#ifdef SOFTFLOAT_ROUND_ODD
99 if ( roundingMode == softfloat_round_odd ) {
100 sig |= roundMask + 1;
101 }
102#endif
103 }
104 sig += roundIncrement;
105 exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
106 roundIncrement = roundMask + 1;
107 if ( roundNearEven && (roundBits<<1 == roundIncrement) ) {
108 roundMask |= roundIncrement;
109 }
110 sig &= ~roundMask;
111 goto packReturn;
112 }
113 if (
114 (0x7FFE < exp)
115 || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig))
116 ) {
117 goto overflow;
118 }
119 }
120 /*------------------------------------------------------------------------
121 *------------------------------------------------------------------------*/
122 if ( roundBits ) {
123 softfloat_exceptionFlags |= softfloat_flag_inexact;
124#ifdef SOFTFLOAT_ROUND_ODD
125 if ( roundingMode == softfloat_round_odd ) {
126 sig = (sig & ~roundMask) | (roundMask + 1);
127 goto packReturn;
128 }
129#endif
130 }
131 sig = (uint64_t) (sig + roundIncrement);
132 if ( sig < roundIncrement ) {
133 ++exp;
134 sig = UINT64_C( 0x8000000000000000 );
135 }
136 roundIncrement = roundMask + 1;
137 if ( roundNearEven && (roundBits<<1 == roundIncrement) ) {
138 roundMask |= roundIncrement;
139 }
140 sig &= ~roundMask;
141 goto packReturn;
142 /*------------------------------------------------------------------------
143 *------------------------------------------------------------------------*/
144 precision80:
145 doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
146 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
147 doIncrement =
148 (roundingMode
149 == (sign ? softfloat_round_min : softfloat_round_max))
150 && sigExtra;
151 }
152 /*------------------------------------------------------------------------
153 *------------------------------------------------------------------------*/
154 if ( 0x7FFD <= (uint32_t) (exp - 1) ) {
155 if ( exp <= 0 ) {
156 /*----------------------------------------------------------------
157 *----------------------------------------------------------------*/
158 isTiny =
159 (softfloat_detectTininess
160 == softfloat_tininess_beforeRounding)
161 || (exp < 0)
162 || ! doIncrement
163 || (sig < UINT64_C( 0xFFFFFFFFFFFFFFFF ));
164 sig64Extra =
165 softfloat_shiftRightJam64Extra( sig, sigExtra, 1 - exp );
166 exp = 0;
167 sig = sig64Extra.v;
168 sigExtra = sig64Extra.extra;
169 if ( sigExtra ) {
170 if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow );
171 softfloat_exceptionFlags |= softfloat_flag_inexact;
172#ifdef SOFTFLOAT_ROUND_ODD
173 if ( roundingMode == softfloat_round_odd ) {
174 sig |= 1;
175 goto packReturn;
176 }
177#endif
178 }
179 doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
180 if (
181 ! roundNearEven
182 && (roundingMode != softfloat_round_near_maxMag)
183 ) {
184 doIncrement =
185 (roundingMode
186 == (sign ? softfloat_round_min : softfloat_round_max))
187 && sigExtra;
188 }
189 if ( doIncrement ) {
190 ++sig;
191 sig &=
192 ~(uint_fast64_t)
193 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
194 & roundNearEven);
195 exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
196 }
197 goto packReturn;
198 }
199 if (
200 (0x7FFE < exp)
201 || ((exp == 0x7FFE) && (sig == UINT64_C( 0xFFFFFFFFFFFFFFFF ))
202 && doIncrement)
203 ) {
204 /*----------------------------------------------------------------
205 *----------------------------------------------------------------*/
206 roundMask = 0;
207 overflow:
208 softfloat_raiseFlags(
209 softfloat_flag_overflow | softfloat_flag_inexact );
210 if (
211 roundNearEven
212 || (roundingMode == softfloat_round_near_maxMag)
213 || (roundingMode
214 == (sign ? softfloat_round_min : softfloat_round_max))
215 ) {
216 exp = 0x7FFF;
217 sig = UINT64_C( 0x8000000000000000 );
218 } else {
219 exp = 0x7FFE;
220 sig = ~roundMask;
221 }
222 goto packReturn;
223 }
224 }
225 /*------------------------------------------------------------------------
226 *------------------------------------------------------------------------*/
227 if ( sigExtra ) {
228 softfloat_exceptionFlags |= softfloat_flag_inexact;
229#ifdef SOFTFLOAT_ROUND_ODD
230 if ( roundingMode == softfloat_round_odd ) {
231 sig |= 1;
232 goto packReturn;
233 }
234#endif
235 }
236 if ( doIncrement ) {
237 ++sig;
238 if ( ! sig ) {
239 ++exp;
240 sig = UINT64_C( 0x8000000000000000 );
241 } else {
242 sig &=
243 ~(uint_fast64_t)
244 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
245 & roundNearEven);
246 }
247 }
248 /*------------------------------------------------------------------------
249 *------------------------------------------------------------------------*/
250 packReturn:
251 uZ.s.signExp = packToExtF80UI64( sign, exp );
252 uZ.s.signif = sig;
253 return uZ.f;
254
255}
256
deps/SoftFloat-3e/source/s_roundPackToF128.c deleted-171
...@@ -1,171 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float128_t
44 softfloat_roundPackToF128(
45 bool sign,
46 int_fast32_t exp,
47 uint_fast64_t sig64,
48 uint_fast64_t sig0,
49 uint_fast64_t sigExtra
50 )
51{
52 uint_fast8_t roundingMode;
53 bool roundNearEven, doIncrement, isTiny;
54 struct uint128_extra sig128Extra;
55 uint_fast64_t uiZ64, uiZ0;
56 struct uint128 sig128;
57 union ui128_f128 uZ;
58
59 /*------------------------------------------------------------------------
60 *------------------------------------------------------------------------*/
61 roundingMode = softfloat_roundingMode;
62 roundNearEven = (roundingMode == softfloat_round_near_even);
63 doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
64 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
65 doIncrement =
66 (roundingMode
67 == (sign ? softfloat_round_min : softfloat_round_max))
68 && sigExtra;
69 }
70 /*------------------------------------------------------------------------
71 *------------------------------------------------------------------------*/
72 if ( 0x7FFD <= (uint32_t) exp ) {
73 if ( exp < 0 ) {
74 /*----------------------------------------------------------------
75 *----------------------------------------------------------------*/
76 isTiny =
77 (softfloat_detectTininess
78 == softfloat_tininess_beforeRounding)
79 || (exp < -1)
80 || ! doIncrement
81 || softfloat_lt128(
82 sig64,
83 sig0,
84 UINT64_C( 0x0001FFFFFFFFFFFF ),
85 UINT64_C( 0xFFFFFFFFFFFFFFFF )
86 );
87 sig128Extra =
88 softfloat_shiftRightJam128Extra( sig64, sig0, sigExtra, -exp );
89 sig64 = sig128Extra.v.v64;
90 sig0 = sig128Extra.v.v0;
91 sigExtra = sig128Extra.extra;
92 exp = 0;
93 if ( isTiny && sigExtra ) {
94 softfloat_raiseFlags( softfloat_flag_underflow );
95 }
96 doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
97 if (
98 ! roundNearEven
99 && (roundingMode != softfloat_round_near_maxMag)
100 ) {
101 doIncrement =
102 (roundingMode
103 == (sign ? softfloat_round_min : softfloat_round_max))
104 && sigExtra;
105 }
106 } else if (
107 (0x7FFD < exp)
108 || ((exp == 0x7FFD)
109 && softfloat_eq128(
110 sig64,
111 sig0,
112 UINT64_C( 0x0001FFFFFFFFFFFF ),
113 UINT64_C( 0xFFFFFFFFFFFFFFFF )
114 )
115 && doIncrement)
116 ) {
117 /*----------------------------------------------------------------
118 *----------------------------------------------------------------*/
119 softfloat_raiseFlags(
120 softfloat_flag_overflow | softfloat_flag_inexact );
121 if (
122 roundNearEven
123 || (roundingMode == softfloat_round_near_maxMag)
124 || (roundingMode
125 == (sign ? softfloat_round_min : softfloat_round_max))
126 ) {
127 uiZ64 = packToF128UI64( sign, 0x7FFF, 0 );
128 uiZ0 = 0;
129 } else {
130 uiZ64 =
131 packToF128UI64(
132 sign, 0x7FFE, UINT64_C( 0x0000FFFFFFFFFFFF ) );
133 uiZ0 = UINT64_C( 0xFFFFFFFFFFFFFFFF );
134 }
135 goto uiZ;
136 }
137 }
138 /*------------------------------------------------------------------------
139 *------------------------------------------------------------------------*/
140 if ( sigExtra ) {
141 softfloat_exceptionFlags |= softfloat_flag_inexact;
142#ifdef SOFTFLOAT_ROUND_ODD
143 if ( roundingMode == softfloat_round_odd ) {
144 sig0 |= 1;
145 goto packReturn;
146 }
147#endif
148 }
149 if ( doIncrement ) {
150 sig128 = softfloat_add128( sig64, sig0, 0, 1 );
151 sig64 = sig128.v64;
152 sig0 =
153 sig128.v0
154 & ~(uint64_t)
155 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
156 & roundNearEven);
157 } else {
158 if ( ! (sig64 | sig0) ) exp = 0;
159 }
160 /*------------------------------------------------------------------------
161 *------------------------------------------------------------------------*/
162 packReturn:
163 uiZ64 = packToF128UI64( sign, exp, sig64 );
164 uiZ0 = sig0;
165 uiZ:
166 uZ.ui.v64 = uiZ64;
167 uZ.ui.v0 = uiZ0;
168 return uZ.f;
169
170}
171
deps/SoftFloat-3e/source/s_roundPackToF16.c deleted-113
...@@ -1,113 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float16_t
44 softfloat_roundPackToF16( bool sign, int_fast16_t exp, uint_fast16_t sig )
45{
46 uint_fast8_t roundingMode;
47 bool roundNearEven;
48 uint_fast8_t roundIncrement, roundBits;
49 bool isTiny;
50 uint_fast16_t uiZ;
51 union ui16_f16 uZ;
52
53 /*------------------------------------------------------------------------
54 *------------------------------------------------------------------------*/
55 roundingMode = softfloat_roundingMode;
56 roundNearEven = (roundingMode == softfloat_round_near_even);
57 roundIncrement = 0x8;
58 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
59 roundIncrement =
60 (roundingMode
61 == (sign ? softfloat_round_min : softfloat_round_max))
62 ? 0xF
63 : 0;
64 }
65 roundBits = sig & 0xF;
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 if ( 0x1D <= (unsigned int) exp ) {
69 if ( exp < 0 ) {
70 /*----------------------------------------------------------------
71 *----------------------------------------------------------------*/
72 isTiny =
73 (softfloat_detectTininess == softfloat_tininess_beforeRounding)
74 || (exp < -1) || (sig + roundIncrement < 0x8000);
75 sig = softfloat_shiftRightJam32( sig, -exp );
76 exp = 0;
77 roundBits = sig & 0xF;
78 if ( isTiny && roundBits ) {
79 softfloat_raiseFlags( softfloat_flag_underflow );
80 }
81 } else if ( (0x1D < exp) || (0x8000 <= sig + roundIncrement) ) {
82 /*----------------------------------------------------------------
83 *----------------------------------------------------------------*/
84 softfloat_raiseFlags(
85 softfloat_flag_overflow | softfloat_flag_inexact );
86 uiZ = packToF16UI( sign, 0x1F, 0 ) - ! roundIncrement;
87 goto uiZ;
88 }
89 }
90 /*------------------------------------------------------------------------
91 *------------------------------------------------------------------------*/
92 sig = (sig + roundIncrement)>>4;
93 if ( roundBits ) {
94 softfloat_exceptionFlags |= softfloat_flag_inexact;
95#ifdef SOFTFLOAT_ROUND_ODD
96 if ( roundingMode == softfloat_round_odd ) {
97 sig |= 1;
98 goto packReturn;
99 }
100#endif
101 }
102 sig &= ~(uint_fast16_t) (! (roundBits ^ 8) & roundNearEven);
103 if ( ! sig ) exp = 0;
104 /*------------------------------------------------------------------------
105 *------------------------------------------------------------------------*/
106 packReturn:
107 uiZ = packToF16UI( sign, exp, sig );
108 uiZ:
109 uZ.ui = uiZ;
110 return uZ.f;
111
112}
113
deps/SoftFloat-3e/source/s_roundPackToF32.c deleted-113
...@@ -1,113 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float32_t
44 softfloat_roundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig )
45{
46 uint_fast8_t roundingMode;
47 bool roundNearEven;
48 uint_fast8_t roundIncrement, roundBits;
49 bool isTiny;
50 uint_fast32_t uiZ;
51 union ui32_f32 uZ;
52
53 /*------------------------------------------------------------------------
54 *------------------------------------------------------------------------*/
55 roundingMode = softfloat_roundingMode;
56 roundNearEven = (roundingMode == softfloat_round_near_even);
57 roundIncrement = 0x40;
58 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
59 roundIncrement =
60 (roundingMode
61 == (sign ? softfloat_round_min : softfloat_round_max))
62 ? 0x7F
63 : 0;
64 }
65 roundBits = sig & 0x7F;
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 if ( 0xFD <= (unsigned int) exp ) {
69 if ( exp < 0 ) {
70 /*----------------------------------------------------------------
71 *----------------------------------------------------------------*/
72 isTiny =
73 (softfloat_detectTininess == softfloat_tininess_beforeRounding)
74 || (exp < -1) || (sig + roundIncrement < 0x80000000);
75 sig = softfloat_shiftRightJam32( sig, -exp );
76 exp = 0;
77 roundBits = sig & 0x7F;
78 if ( isTiny && roundBits ) {
79 softfloat_raiseFlags( softfloat_flag_underflow );
80 }
81 } else if ( (0xFD < exp) || (0x80000000 <= sig + roundIncrement) ) {
82 /*----------------------------------------------------------------
83 *----------------------------------------------------------------*/
84 softfloat_raiseFlags(
85 softfloat_flag_overflow | softfloat_flag_inexact );
86 uiZ = packToF32UI( sign, 0xFF, 0 ) - ! roundIncrement;
87 goto uiZ;
88 }
89 }
90 /*------------------------------------------------------------------------
91 *------------------------------------------------------------------------*/
92 sig = (sig + roundIncrement)>>7;
93 if ( roundBits ) {
94 softfloat_exceptionFlags |= softfloat_flag_inexact;
95#ifdef SOFTFLOAT_ROUND_ODD
96 if ( roundingMode == softfloat_round_odd ) {
97 sig |= 1;
98 goto packReturn;
99 }
100#endif
101 }
102 sig &= ~(uint_fast32_t) (! (roundBits ^ 0x40) & roundNearEven);
103 if ( ! sig ) exp = 0;
104 /*------------------------------------------------------------------------
105 *------------------------------------------------------------------------*/
106 packReturn:
107 uiZ = packToF32UI( sign, exp, sig );
108 uiZ:
109 uZ.ui = uiZ;
110 return uZ.f;
111
112}
113
deps/SoftFloat-3e/source/s_roundPackToF64.c deleted-117
...@@ -1,117 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42
43float64_t
44 softfloat_roundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig )
45{
46 uint_fast8_t roundingMode;
47 bool roundNearEven;
48 uint_fast16_t roundIncrement, roundBits;
49 bool isTiny;
50 uint_fast64_t uiZ;
51 union ui64_f64 uZ;
52
53 /*------------------------------------------------------------------------
54 *------------------------------------------------------------------------*/
55 roundingMode = softfloat_roundingMode;
56 roundNearEven = (roundingMode == softfloat_round_near_even);
57 roundIncrement = 0x200;
58 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
59 roundIncrement =
60 (roundingMode
61 == (sign ? softfloat_round_min : softfloat_round_max))
62 ? 0x3FF
63 : 0;
64 }
65 roundBits = sig & 0x3FF;
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 if ( 0x7FD <= (uint16_t) exp ) {
69 if ( exp < 0 ) {
70 /*----------------------------------------------------------------
71 *----------------------------------------------------------------*/
72 isTiny =
73 (softfloat_detectTininess == softfloat_tininess_beforeRounding)
74 || (exp < -1)
75 || (sig + roundIncrement < UINT64_C( 0x8000000000000000 ));
76 sig = softfloat_shiftRightJam64( sig, -exp );
77 exp = 0;
78 roundBits = sig & 0x3FF;
79 if ( isTiny && roundBits ) {
80 softfloat_raiseFlags( softfloat_flag_underflow );
81 }
82 } else if (
83 (0x7FD < exp)
84 || (UINT64_C( 0x8000000000000000 ) <= sig + roundIncrement)
85 ) {
86 /*----------------------------------------------------------------
87 *----------------------------------------------------------------*/
88 softfloat_raiseFlags(
89 softfloat_flag_overflow | softfloat_flag_inexact );
90 uiZ = packToF64UI( sign, 0x7FF, 0 ) - ! roundIncrement;
91 goto uiZ;
92 }
93 }
94 /*------------------------------------------------------------------------
95 *------------------------------------------------------------------------*/
96 sig = (sig + roundIncrement)>>10;
97 if ( roundBits ) {
98 softfloat_exceptionFlags |= softfloat_flag_inexact;
99#ifdef SOFTFLOAT_ROUND_ODD
100 if ( roundingMode == softfloat_round_odd ) {
101 sig |= 1;
102 goto packReturn;
103 }
104#endif
105 }
106 sig &= ~(uint_fast64_t) (! (roundBits ^ 0x200) & roundNearEven);
107 if ( ! sig ) exp = 0;
108 /*------------------------------------------------------------------------
109 *------------------------------------------------------------------------*/
110 packReturn:
111 uiZ = packToF64UI( sign, exp, sig );
112 uiZ:
113 uZ.ui = uiZ;
114 return uZ.f;
115
116}
117
deps/SoftFloat-3e/source/s_roundToI32.c deleted-98
...@@ -1,98 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast32_t
45 softfloat_roundToI32(
46 bool sign, uint_fast64_t sig, uint_fast8_t roundingMode, bool exact )
47{
48 uint_fast16_t roundIncrement, roundBits;
49 uint_fast32_t sig32;
50 union { uint32_t ui; int32_t i; } uZ;
51 int_fast32_t z;
52
53 /*------------------------------------------------------------------------
54 *------------------------------------------------------------------------*/
55 roundIncrement = 0x800;
56 if (
57 (roundingMode != softfloat_round_near_maxMag)
58 && (roundingMode != softfloat_round_near_even)
59 ) {
60 roundIncrement = 0;
61 if (
62 sign
63 ? (roundingMode == softfloat_round_min)
64#ifdef SOFTFLOAT_ROUND_ODD
65 || (roundingMode == softfloat_round_odd)
66#endif
67 : (roundingMode == softfloat_round_max)
68 ) {
69 roundIncrement = 0xFFF;
70 }
71 }
72 roundBits = sig & 0xFFF;
73 sig += roundIncrement;
74 if ( sig & UINT64_C( 0xFFFFF00000000000 ) ) goto invalid;
75 sig32 = sig>>12;
76 if (
77 (roundBits == 0x800) && (roundingMode == softfloat_round_near_even)
78 ) {
79 sig32 &= ~(uint_fast32_t) 1;
80 }
81 uZ.ui = sign ? -sig32 : sig32;
82 z = uZ.i;
83 if ( z && ((z < 0) ^ sign) ) goto invalid;
84 if ( roundBits ) {
85#ifdef SOFTFLOAT_ROUND_ODD
86 if ( roundingMode == softfloat_round_odd ) z |= 1;
87#endif
88 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
89 }
90 return z;
91 /*------------------------------------------------------------------------
92 *------------------------------------------------------------------------*/
93 invalid:
94 softfloat_raiseFlags( softfloat_flag_invalid );
95 return sign ? i32_fromNegOverflow : i32_fromPosOverflow;
96
97}
98
deps/SoftFloat-3e/source/s_roundToI64.c deleted-101
...@@ -1,101 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44int_fast64_t
45 softfloat_roundToI64(
46 bool sign,
47 uint_fast64_t sig,
48 uint_fast64_t sigExtra,
49 uint_fast8_t roundingMode,
50 bool exact
51 )
52{
53 union { uint64_t ui; int64_t i; } uZ;
54 int_fast64_t z;
55
56 /*------------------------------------------------------------------------
57 *------------------------------------------------------------------------*/
58 if (
59 (roundingMode == softfloat_round_near_maxMag)
60 || (roundingMode == softfloat_round_near_even)
61 ) {
62 if ( UINT64_C( 0x8000000000000000 ) <= sigExtra ) goto increment;
63 } else {
64 if (
65 sigExtra
66 && (sign
67 ? (roundingMode == softfloat_round_min)
68#ifdef SOFTFLOAT_ROUND_ODD
69 || (roundingMode == softfloat_round_odd)
70#endif
71 : (roundingMode == softfloat_round_max))
72 ) {
73 increment:
74 ++sig;
75 if ( !sig ) goto invalid;
76 if (
77 (sigExtra == UINT64_C( 0x8000000000000000 ))
78 && (roundingMode == softfloat_round_near_even)
79 ) {
80 sig &= ~(uint_fast64_t) 1;
81 }
82 }
83 }
84 uZ.ui = sign ? -sig : sig;
85 z = uZ.i;
86 if ( z && ((z < 0) ^ sign) ) goto invalid;
87 if ( sigExtra ) {
88#ifdef SOFTFLOAT_ROUND_ODD
89 if ( roundingMode == softfloat_round_odd ) z |= 1;
90#endif
91 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
92 }
93 return z;
94 /*------------------------------------------------------------------------
95 *------------------------------------------------------------------------*/
96 invalid:
97 softfloat_raiseFlags( softfloat_flag_invalid );
98 return sign ? i64_fromNegOverflow : i64_fromPosOverflow;
99
100}
101
deps/SoftFloat-3e/source/s_roundToUI32.c deleted-93
...@@ -1,93 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast32_t
45 softfloat_roundToUI32(
46 bool sign, uint_fast64_t sig, uint_fast8_t roundingMode, bool exact )
47{
48 uint_fast16_t roundIncrement, roundBits;
49 uint_fast32_t z;
50
51 /*------------------------------------------------------------------------
52 *------------------------------------------------------------------------*/
53 roundIncrement = 0x800;
54 if (
55 (roundingMode != softfloat_round_near_maxMag)
56 && (roundingMode != softfloat_round_near_even)
57 ) {
58 roundIncrement = 0;
59 if ( sign ) {
60 if ( !sig ) return 0;
61 if ( roundingMode == softfloat_round_min ) goto invalid;
62#ifdef SOFTFLOAT_ROUND_ODD
63 if ( roundingMode == softfloat_round_odd ) goto invalid;
64#endif
65 } else {
66 if ( roundingMode == softfloat_round_max ) roundIncrement = 0xFFF;
67 }
68 }
69 roundBits = sig & 0xFFF;
70 sig += roundIncrement;
71 if ( sig & UINT64_C( 0xFFFFF00000000000 ) ) goto invalid;
72 z = sig>>12;
73 if (
74 (roundBits == 0x800) && (roundingMode == softfloat_round_near_even)
75 ) {
76 z &= ~(uint_fast32_t) 1;
77 }
78 if ( sign && z ) goto invalid;
79 if ( roundBits ) {
80#ifdef SOFTFLOAT_ROUND_ODD
81 if ( roundingMode == softfloat_round_odd ) z |= 1;
82#endif
83 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
84 }
85 return z;
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 invalid:
89 softfloat_raiseFlags( softfloat_flag_invalid );
90 return sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
91
92}
93
deps/SoftFloat-3e/source/s_roundToUI64.c deleted-97
...@@ -1,97 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44uint_fast64_t
45 softfloat_roundToUI64(
46 bool sign,
47 uint_fast64_t sig,
48 uint_fast64_t sigExtra,
49 uint_fast8_t roundingMode,
50 bool exact
51 )
52{
53
54 /*------------------------------------------------------------------------
55 *------------------------------------------------------------------------*/
56 if (
57 (roundingMode == softfloat_round_near_maxMag)
58 || (roundingMode == softfloat_round_near_even)
59 ) {
60 if ( UINT64_C( 0x8000000000000000 ) <= sigExtra ) goto increment;
61 } else {
62 if ( sign ) {
63 if ( !(sig | sigExtra) ) return 0;
64 if ( roundingMode == softfloat_round_min ) goto invalid;
65#ifdef SOFTFLOAT_ROUND_ODD
66 if ( roundingMode == softfloat_round_odd ) goto invalid;
67#endif
68 } else {
69 if ( (roundingMode == softfloat_round_max) && sigExtra ) {
70 increment:
71 ++sig;
72 if ( !sig ) goto invalid;
73 if (
74 (sigExtra == UINT64_C( 0x8000000000000000 ))
75 && (roundingMode == softfloat_round_near_even)
76 ) {
77 sig &= ~(uint_fast64_t) 1;
78 }
79 }
80 }
81 }
82 if ( sign && sig ) goto invalid;
83 if ( sigExtra ) {
84#ifdef SOFTFLOAT_ROUND_ODD
85 if ( roundingMode == softfloat_round_odd ) sig |= 1;
86#endif
87 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
88 }
89 return sig;
90 /*------------------------------------------------------------------------
91 *------------------------------------------------------------------------*/
92 invalid:
93 softfloat_raiseFlags( softfloat_flag_invalid );
94 return sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
95
96}
97
deps/SoftFloat-3e/source/s_shiftLeftM.c deleted-91
...@@ -1,91 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39
40#ifndef softfloat_shiftLeftM
41
42#define softfloat_shiftLeftM softfloat_shiftLeftM
43#include "primitives.h"
44
45void
46 softfloat_shiftLeftM(
47 uint_fast8_t size_words,
48 const uint32_t *aPtr,
49 uint32_t dist,
50 uint32_t *zPtr
51 )
52{
53 uint32_t wordDist;
54 uint_fast8_t innerDist;
55 uint32_t *destPtr;
56 uint_fast8_t i;
57
58 wordDist = dist>>5;
59 if ( wordDist < size_words ) {
60 aPtr += indexMultiwordLoBut( size_words, wordDist );
61 innerDist = dist & 31;
62 if ( innerDist ) {
63 softfloat_shortShiftLeftM(
64 size_words - wordDist,
65 aPtr,
66 innerDist,
67 zPtr + indexMultiwordHiBut( size_words, wordDist )
68 );
69 if ( ! wordDist ) return;
70 } else {
71 aPtr += indexWordHi( size_words - wordDist );
72 destPtr = zPtr + indexWordHi( size_words );
73 for ( i = size_words - wordDist; i; --i ) {
74 *destPtr = *aPtr;
75 aPtr -= wordIncr;
76 destPtr -= wordIncr;
77 }
78 }
79 zPtr += indexMultiwordLo( size_words, wordDist );
80 } else {
81 wordDist = size_words;
82 }
83 do {
84 *zPtr++ = 0;
85 --wordDist;
86 } while ( wordDist );
87
88}
89
90#endif
91
deps/SoftFloat-3e/source/s_shiftNormSigF128M.c deleted-78
...@@ -1,78 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40
41int
42 softfloat_shiftNormSigF128M(
43 const uint32_t *wPtr, uint_fast8_t shiftDist, uint32_t *sigPtr )
44{
45 uint32_t wordSig;
46 int32_t exp;
47 uint32_t leadingBit;
48
49 wordSig = wPtr[indexWordHi( 4 )];
50 exp = expF128UI96( wordSig );
51 if ( exp ) {
52 softfloat_shortShiftLeft128M( wPtr, shiftDist, sigPtr );
53 leadingBit = 0x00010000<<shiftDist;
54 sigPtr[indexWordHi( 4 )] =
55 (sigPtr[indexWordHi( 4 )] & (leadingBit - 1)) | leadingBit;
56 } else {
57 exp = 16;
58 wordSig &= 0x7FFFFFFF;
59 if ( ! wordSig ) {
60 exp = -16;
61 wordSig = wPtr[indexWord( 4, 2 )];
62 if ( ! wordSig ) {
63 exp = -48;
64 wordSig = wPtr[indexWord( 4, 1 )];
65 if ( ! wordSig ) {
66 wordSig = wPtr[indexWord( 4, 0 )];
67 if ( ! wordSig ) return -128;
68 exp = -80;
69 }
70 }
71 }
72 exp -= softfloat_countLeadingZeros32( wordSig );
73 softfloat_shiftLeft128M( wPtr, 1 - exp + shiftDist, sigPtr );
74 }
75 return exp;
76
77}
78
deps/SoftFloat-3e/source/s_shiftRightJam128.c deleted-69
...@@ -1,69 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shiftRightJam128
42
43struct uint128
44 softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t dist )
45{
46 uint_fast8_t u8NegDist;
47 struct uint128 z;
48
49 if ( dist < 64 ) {
50 u8NegDist = -dist;
51 z.v64 = a64>>dist;
52 z.v0 =
53 a64<<(u8NegDist & 63) | a0>>dist
54 | ((uint64_t) (a0<<(u8NegDist & 63)) != 0);
55 } else {
56 z.v64 = 0;
57 z.v0 =
58 (dist < 127)
59 ? a64>>(dist & 63)
60 | (((a64 & (((uint_fast64_t) 1<<(dist & 63)) - 1)) | a0)
61 != 0)
62 : ((a64 | a0) != 0);
63 }
64 return z;
65
66}
67
68#endif
69
deps/SoftFloat-3e/source/s_shiftRightJam128Extra.c deleted-77
...@@ -1,77 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shiftRightJam128Extra
42
43struct uint128_extra
44 softfloat_shiftRightJam128Extra(
45 uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist )
46{
47 uint_fast8_t u8NegDist;
48 struct uint128_extra z;
49
50 u8NegDist = -dist;
51 if ( dist < 64 ) {
52 z.v.v64 = a64>>dist;
53 z.v.v0 = a64<<(u8NegDist & 63) | a0>>dist;
54 z.extra = a0<<(u8NegDist & 63);
55 } else {
56 z.v.v64 = 0;
57 if ( dist == 64 ) {
58 z.v.v0 = a64;
59 z.extra = a0;
60 } else {
61 extra |= a0;
62 if ( dist < 128 ) {
63 z.v.v0 = a64>>(dist & 63);
64 z.extra = a64<<(u8NegDist & 63);
65 } else {
66 z.v.v0 = 0;
67 z.extra = (dist == 128) ? a64 : (a64 != 0);
68 }
69 }
70 }
71 z.extra |= (extra != 0);
72 return z;
73
74}
75
76#endif
77
deps/SoftFloat-3e/source/s_shiftRightJam256M.c deleted-126
...@@ -1,126 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shiftRightJam256M
42
43static
44 void
45 softfloat_shortShiftRightJamM(
46 uint_fast8_t size_words,
47 const uint64_t *aPtr,
48 uint_fast8_t dist,
49 uint64_t *zPtr
50 )
51{
52 uint_fast8_t uNegDist;
53 unsigned int index, lastIndex;
54 uint64_t partWordZ, wordA;
55
56 uNegDist = -dist;
57 index = indexWordLo( size_words );
58 lastIndex = indexWordHi( size_words );
59 wordA = aPtr[index];
60 partWordZ = wordA>>dist;
61 if ( partWordZ<<dist != wordA ) partWordZ |= 1;
62 while ( index != lastIndex ) {
63 wordA = aPtr[index + wordIncr];
64 zPtr[index] = wordA<<(uNegDist & 63) | partWordZ;
65 index += wordIncr;
66 partWordZ = wordA>>dist;
67 }
68 zPtr[index] = partWordZ;
69
70}
71
72void
73 softfloat_shiftRightJam256M(
74 const uint64_t *aPtr, uint_fast32_t dist, uint64_t *zPtr )
75{
76 uint64_t wordJam;
77 uint_fast32_t wordDist;
78 uint64_t *ptr;
79 uint_fast8_t i, innerDist;
80
81 wordJam = 0;
82 wordDist = dist>>6;
83 if ( wordDist ) {
84 if ( 4 < wordDist ) wordDist = 4;
85 ptr = (uint64_t *) (aPtr + indexMultiwordLo( 4, wordDist ));
86 i = wordDist;
87 do {
88 wordJam = *ptr++;
89 if ( wordJam ) break;
90 --i;
91 } while ( i );
92 ptr = zPtr;
93 }
94 if ( wordDist < 4 ) {
95 aPtr += indexMultiwordHiBut( 4, wordDist );
96 innerDist = dist & 63;
97 if ( innerDist ) {
98 softfloat_shortShiftRightJamM(
99 4 - wordDist,
100 aPtr,
101 innerDist,
102 zPtr + indexMultiwordLoBut( 4, wordDist )
103 );
104 if ( ! wordDist ) goto wordJam;
105 } else {
106 aPtr += indexWordLo( 4 - wordDist );
107 ptr = zPtr + indexWordLo( 4 );
108 for ( i = 4 - wordDist; i; --i ) {
109 *ptr = *aPtr;
110 aPtr += wordIncr;
111 ptr += wordIncr;
112 }
113 }
114 ptr = zPtr + indexMultiwordHi( 4, wordDist );
115 }
116 do {
117 *ptr++ = 0;
118 --wordDist;
119 } while ( wordDist );
120 wordJam:
121 if ( wordJam ) zPtr[indexWordLo( 4 )] |= 1;
122
123}
124
125#endif
126
deps/SoftFloat-3e/source/s_shiftRightJam32.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39
40#ifndef softfloat_shiftRightJam32
41
42uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist )
43{
44
45 return
46 (dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0);
47
48}
49
50#endif
51
deps/SoftFloat-3e/source/s_shiftRightJam64.c deleted-51
...@@ -1,51 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39
40#ifndef softfloat_shiftRightJam64
41
42uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist )
43{
44
45 return
46 (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0);
47
48}
49
50#endif
51
deps/SoftFloat-3e/source/s_shiftRightJam64Extra.c deleted-62
...@@ -1,62 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shiftRightJam64Extra
42
43struct uint64_extra
44 softfloat_shiftRightJam64Extra(
45 uint64_t a, uint64_t extra, uint_fast32_t dist )
46{
47 struct uint64_extra z;
48
49 if ( dist < 64 ) {
50 z.v = a>>dist;
51 z.extra = a<<(-dist & 63);
52 } else {
53 z.v = 0;
54 z.extra = (dist == 64) ? a : (a != 0);
55 }
56 z.extra |= (extra != 0);
57 return z;
58
59}
60
61#endif
62
deps/SoftFloat-3e/source/s_shiftRightJamM.c deleted-101
...@@ -1,101 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39
40#ifndef softfloat_shiftRightJamM
41
42#define softfloat_shiftRightJamM softfloat_shiftRightJamM
43#include "primitives.h"
44
45void
46 softfloat_shiftRightJamM(
47 uint_fast8_t size_words,
48 const uint32_t *aPtr,
49 uint32_t dist,
50 uint32_t *zPtr
51 )
52{
53 uint32_t wordJam, wordDist, *ptr;
54 uint_fast8_t i, innerDist;
55
56 wordJam = 0;
57 wordDist = dist>>5;
58 if ( wordDist ) {
59 if ( size_words < wordDist ) wordDist = size_words;
60 ptr = (uint32_t *) (aPtr + indexMultiwordLo( size_words, wordDist ));
61 i = wordDist;
62 do {
63 wordJam = *ptr++;
64 if ( wordJam ) break;
65 --i;
66 } while ( i );
67 ptr = zPtr;
68 }
69 if ( wordDist < size_words ) {
70 aPtr += indexMultiwordHiBut( size_words, wordDist );
71 innerDist = dist & 31;
72 if ( innerDist ) {
73 softfloat_shortShiftRightJamM(
74 size_words - wordDist,
75 aPtr,
76 innerDist,
77 zPtr + indexMultiwordLoBut( size_words, wordDist )
78 );
79 if ( ! wordDist ) goto wordJam;
80 } else {
81 aPtr += indexWordLo( size_words - wordDist );
82 ptr = zPtr + indexWordLo( size_words );
83 for ( i = size_words - wordDist; i; --i ) {
84 *ptr = *aPtr;
85 aPtr += wordIncr;
86 ptr += wordIncr;
87 }
88 }
89 ptr = zPtr + indexMultiwordHi( size_words, wordDist );
90 }
91 do {
92 *ptr++ = 0;
93 --wordDist;
94 } while ( wordDist );
95 wordJam:
96 if ( wordJam ) zPtr[indexWordLo( size_words )] |= 1;
97
98}
99
100#endif
101
deps/SoftFloat-3e/source/s_shiftRightM.c deleted-91
...@@ -1,91 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39
40#ifndef softfloat_shiftRightM
41
42#define softfloat_shiftRightM softfloat_shiftRightM
43#include "primitives.h"
44
45void
46 softfloat_shiftRightM(
47 uint_fast8_t size_words,
48 const uint32_t *aPtr,
49 uint32_t dist,
50 uint32_t *zPtr
51 )
52{
53 uint32_t wordDist;
54 uint_fast8_t innerDist;
55 uint32_t *destPtr;
56 uint_fast8_t i;
57
58 wordDist = dist>>5;
59 if ( wordDist < size_words ) {
60 aPtr += indexMultiwordHiBut( size_words, wordDist );
61 innerDist = dist & 31;
62 if ( innerDist ) {
63 softfloat_shortShiftRightM(
64 size_words - wordDist,
65 aPtr,
66 innerDist,
67 zPtr + indexMultiwordLoBut( size_words, wordDist )
68 );
69 if ( ! wordDist ) return;
70 } else {
71 aPtr += indexWordLo( size_words - wordDist );
72 destPtr = zPtr + indexWordLo( size_words );
73 for ( i = size_words - wordDist; i; --i ) {
74 *destPtr = *aPtr;
75 aPtr += wordIncr;
76 destPtr += wordIncr;
77 }
78 }
79 zPtr += indexMultiwordHi( size_words, wordDist );
80 } else {
81 wordDist = size_words;
82 }
83 do {
84 *zPtr++ = 0;
85 --wordDist;
86 } while ( wordDist );
87
88}
89
90#endif
91
deps/SoftFloat-3e/source/s_shortShiftLeft128.c deleted-55
...@@ -1,55 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shortShiftLeft128
42
43struct uint128
44 softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
45{
46 struct uint128 z;
47
48 z.v64 = a64<<dist | a0>>(-dist & 63);
49 z.v0 = a0<<dist;
50 return z;
51
52}
53
54#endif
55
deps/SoftFloat-3e/source/s_shortShiftLeft64To96M.c deleted-56
...@@ -1,56 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shortShiftLeft64To96M
42
43void
44 softfloat_shortShiftLeft64To96M(
45 uint64_t a, uint_fast8_t dist, uint32_t *zPtr )
46{
47
48 zPtr[indexWord( 3, 0 )] = (uint32_t) a<<dist;
49 a >>= 32 - dist;
50 zPtr[indexWord( 3, 2 )] = a>>32;
51 zPtr[indexWord( 3, 1 )] = a;
52
53}
54
55#endif
56
deps/SoftFloat-3e/source/s_shortShiftLeftM.c deleted-70
...@@ -1,70 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shortShiftLeftM
42
43void
44 softfloat_shortShiftLeftM(
45 uint_fast8_t size_words,
46 const uint32_t *aPtr,
47 uint_fast8_t dist,
48 uint32_t *zPtr
49 )
50{
51 uint_fast8_t uNegDist;
52 unsigned int index, lastIndex;
53 uint32_t partWordZ, wordA;
54
55 uNegDist = -dist;
56 index = indexWordHi( size_words );
57 lastIndex = indexWordLo( size_words );
58 partWordZ = aPtr[index]<<dist;
59 while ( index != lastIndex ) {
60 wordA = aPtr[index - wordIncr];
61 zPtr[index] = partWordZ | wordA>>(uNegDist & 31);
62 index -= wordIncr;
63 partWordZ = wordA<<dist;
64 }
65 zPtr[index] = partWordZ;
66
67}
68
69#endif
70
deps/SoftFloat-3e/source/s_shortShiftRight128.c deleted-55
...@@ -1,55 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shortShiftRight128
42
43struct uint128
44 softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
45{
46 struct uint128 z;
47
48 z.v64 = a64>>dist;
49 z.v0 = a64<<(-dist & 63) | a0>>dist;
50 return z;
51
52}
53
54#endif
55
deps/SoftFloat-3e/source/s_shortShiftRightExtendM.c deleted-73
...@@ -1,73 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shortShiftRightExtendM
42
43void
44 softfloat_shortShiftRightExtendM(
45 uint_fast8_t size_words,
46 const uint32_t *aPtr,
47 uint_fast8_t dist,
48 uint32_t *zPtr
49 )
50{
51 uint_fast8_t uNegDist;
52 unsigned int indexA, lastIndexA;
53 uint32_t partWordZ, wordA;
54
55 uNegDist = -dist;
56 indexA = indexWordLo( size_words );
57 lastIndexA = indexWordHi( size_words );
58 zPtr += indexWordLo( size_words + 1 );
59 partWordZ = 0;
60 for (;;) {
61 wordA = aPtr[indexA];
62 *zPtr = wordA<<(uNegDist & 31) | partWordZ;
63 zPtr += wordIncr;
64 partWordZ = wordA>>dist;
65 if ( indexA == lastIndexA ) break;
66 indexA += wordIncr;
67 }
68 *zPtr = partWordZ;
69
70}
71
72#endif
73
deps/SoftFloat-3e/source/s_shortShiftRightJam128.c deleted-60
...@@ -1,60 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shortShiftRightJam128
42
43struct uint128
44 softfloat_shortShiftRightJam128(
45 uint64_t a64, uint64_t a0, uint_fast8_t dist )
46{
47 uint_fast8_t uNegDist;
48 struct uint128 z;
49
50 uNegDist = -dist;
51 z.v64 = a64>>dist;
52 z.v0 =
53 a64<<(uNegDist & 63) | a0>>dist
54 | ((uint64_t) (a0<<(uNegDist & 63)) != 0);
55 return z;
56
57}
58
59#endif
60
deps/SoftFloat-3e/source/s_shortShiftRightJam128Extra.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shortShiftRightJam128Extra
42
43struct uint128_extra
44 softfloat_shortShiftRightJam128Extra(
45 uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist )
46{
47 uint_fast8_t uNegDist;
48 struct uint128_extra z;
49
50 uNegDist = -dist;
51 z.v.v64 = a64>>dist;
52 z.v.v0 = a64<<(uNegDist & 63) | a0>>dist;
53 z.extra = a0<<(uNegDist & 63) | (extra != 0);
54 return z;
55
56}
57
58#endif
59
deps/SoftFloat-3e/source/s_shortShiftRightJam64.c deleted-50
...@@ -1,50 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39
40#ifndef softfloat_shortShiftRightJam64
41
42uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist )
43{
44
45 return a>>dist | ((a & (((uint_fast64_t) 1<<dist) - 1)) != 0);
46
47}
48
49#endif
50
deps/SoftFloat-3e/source/s_shortShiftRightJam64Extra.c deleted-56
...@@ -1,56 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shortShiftRightJam64Extra
42
43struct uint64_extra
44 softfloat_shortShiftRightJam64Extra(
45 uint64_t a, uint64_t extra, uint_fast8_t dist )
46{
47 struct uint64_extra z;
48
49 z.v = a>>dist;
50 z.extra = a<<(-dist & 63) | (extra != 0);
51 return z;
52
53}
54
55#endif
56
deps/SoftFloat-3e/source/s_shortShiftRightJamM.c deleted-72
...@@ -1,72 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shortShiftRightJamM
42
43void
44 softfloat_shortShiftRightJamM(
45 uint_fast8_t size_words,
46 const uint32_t *aPtr,
47 uint_fast8_t dist,
48 uint32_t *zPtr
49 )
50{
51 uint_fast8_t uNegDist;
52 unsigned int index, lastIndex;
53 uint32_t partWordZ, wordA;
54
55 uNegDist = -dist;
56 index = indexWordLo( size_words );
57 lastIndex = indexWordHi( size_words );
58 wordA = aPtr[index];
59 partWordZ = wordA>>dist;
60 if ( partWordZ<<dist != wordA ) partWordZ |= 1;
61 while ( index != lastIndex ) {
62 wordA = aPtr[index + wordIncr];
63 zPtr[index] = wordA<<(uNegDist & 31) | partWordZ;
64 index += wordIncr;
65 partWordZ = wordA>>dist;
66 }
67 zPtr[index] = partWordZ;
68
69}
70
71#endif
72
deps/SoftFloat-3e/source/s_shortShiftRightM.c deleted-70
...@@ -1,70 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_shortShiftRightM
42
43void
44 softfloat_shortShiftRightM(
45 uint_fast8_t size_words,
46 const uint32_t *aPtr,
47 uint_fast8_t dist,
48 uint32_t *zPtr
49 )
50{
51 uint_fast8_t uNegDist;
52 unsigned int index, lastIndex;
53 uint32_t partWordZ, wordA;
54
55 uNegDist = -dist;
56 index = indexWordLo( size_words );
57 lastIndex = indexWordHi( size_words );
58 partWordZ = aPtr[index]>>dist;
59 while ( index != lastIndex ) {
60 wordA = aPtr[index + wordIncr];
61 zPtr[index] = wordA<<(uNegDist & 31) | partWordZ;
62 index += wordIncr;
63 partWordZ = wordA>>dist;
64 }
65 zPtr[index] = partWordZ;
66
67}
68
69#endif
70
deps/SoftFloat-3e/source/s_sub128.c deleted-55
...@@ -1,55 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_sub128
42
43struct uint128
44 softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
45{
46 struct uint128 z;
47
48 z.v0 = a0 - b0;
49 z.v64 = a64 - b64 - (a0 < b0);
50 return z;
51
52}
53
54#endif
55
deps/SoftFloat-3e/source/s_sub1XM.c deleted-60
...@@ -1,60 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_sub1XM
42
43void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr )
44{
45 unsigned int index, lastIndex;
46 uint32_t wordA;
47
48 index = indexWordLo( size_words );
49 lastIndex = indexWordHi( size_words );
50 for (;;) {
51 wordA = zPtr[index];
52 zPtr[index] = wordA - 1;
53 if ( wordA || (index == lastIndex) ) break;
54 index += wordIncr;
55 }
56
57}
58
59#endif
60
deps/SoftFloat-3e/source/s_sub256M.c deleted-65
...@@ -1,65 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_sub256M
42
43void
44 softfloat_sub256M(
45 const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr )
46{
47 unsigned int index;
48 uint_fast8_t borrow;
49 uint64_t wordA, wordB;
50
51 index = indexWordLo( 4 );
52 borrow = 0;
53 for (;;) {
54 wordA = aPtr[index];
55 wordB = bPtr[index];
56 zPtr[index] = wordA - wordB - borrow;
57 if ( index == indexWordHi( 4 ) ) break;
58 borrow = borrow ? (wordA <= wordB) : (wordA < wordB);
59 index += wordIncr;
60 }
61
62}
63
64#endif
65
deps/SoftFloat-3e/source/s_subM.c deleted-70
...@@ -1,70 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "primitiveTypes.h"
40
41#ifndef softfloat_subM
42
43void
44 softfloat_subM(
45 uint_fast8_t size_words,
46 const uint32_t *aPtr,
47 const uint32_t *bPtr,
48 uint32_t *zPtr
49 )
50{
51 unsigned int index, lastIndex;
52 uint_fast8_t borrow;
53 uint32_t wordA, wordB;
54
55 index = indexWordLo( size_words );
56 lastIndex = indexWordHi( size_words );
57 borrow = 0;
58 for (;;) {
59 wordA = aPtr[index];
60 wordB = bPtr[index];
61 zPtr[index] = wordA - wordB - borrow;
62 if ( index == lastIndex ) break;
63 borrow = borrow ? (wordA <= wordB) : (wordA < wordB);
64 index += wordIncr;
65 }
66
67}
68
69#endif
70
deps/SoftFloat-3e/source/s_subMagsExtF80.c deleted-158
...@@ -1,158 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44extFloat80_t
45 softfloat_subMagsExtF80(
46 uint_fast16_t uiA64,
47 uint_fast64_t uiA0,
48 uint_fast16_t uiB64,
49 uint_fast64_t uiB0,
50 bool signZ
51 )
52{
53 int_fast32_t expA;
54 uint_fast64_t sigA;
55 int_fast32_t expB;
56 uint_fast64_t sigB;
57 int_fast32_t expDiff;
58 uint_fast16_t uiZ64;
59 uint_fast64_t uiZ0;
60 int_fast32_t expZ;
61 uint_fast64_t sigExtra;
62 struct uint128 sig128, uiZ;
63 union { struct extFloat80M s; extFloat80_t f; } uZ;
64
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 expA = expExtF80UI64( uiA64 );
68 sigA = uiA0;
69 expB = expExtF80UI64( uiB64 );
70 sigB = uiB0;
71 /*------------------------------------------------------------------------
72 *------------------------------------------------------------------------*/
73 expDiff = expA - expB;
74 if ( 0 < expDiff ) goto expABigger;
75 if ( expDiff < 0 ) goto expBBigger;
76 if ( expA == 0x7FFF ) {
77 if ( (sigA | sigB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
78 goto propagateNaN;
79 }
80 softfloat_raiseFlags( softfloat_flag_invalid );
81 uiZ64 = defaultNaNExtF80UI64;
82 uiZ0 = defaultNaNExtF80UI0;
83 goto uiZ;
84 }
85 /*------------------------------------------------------------------------
86 *------------------------------------------------------------------------*/
87 expZ = expA;
88 if ( ! expZ ) expZ = 1;
89 sigExtra = 0;
90 if ( sigB < sigA ) goto aBigger;
91 if ( sigA < sigB ) goto bBigger;
92 uiZ64 =
93 packToExtF80UI64( (softfloat_roundingMode == softfloat_round_min), 0 );
94 uiZ0 = 0;
95 goto uiZ;
96 /*------------------------------------------------------------------------
97 *------------------------------------------------------------------------*/
98 expBBigger:
99 if ( expB == 0x7FFF ) {
100 if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN;
101 uiZ64 = packToExtF80UI64( signZ ^ 1, 0x7FFF );
102 uiZ0 = UINT64_C( 0x8000000000000000 );
103 goto uiZ;
104 }
105 if ( ! expA ) {
106 ++expDiff;
107 sigExtra = 0;
108 if ( ! expDiff ) goto newlyAlignedBBigger;
109 }
110 sig128 = softfloat_shiftRightJam128( sigA, 0, -expDiff );
111 sigA = sig128.v64;
112 sigExtra = sig128.v0;
113 newlyAlignedBBigger:
114 expZ = expB;
115 bBigger:
116 signZ = ! signZ;
117 sig128 = softfloat_sub128( sigB, 0, sigA, sigExtra );
118 goto normRoundPack;
119 /*------------------------------------------------------------------------
120 *------------------------------------------------------------------------*/
121 expABigger:
122 if ( expA == 0x7FFF ) {
123 if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN;
124 uiZ64 = uiA64;
125 uiZ0 = uiA0;
126 goto uiZ;
127 }
128 if ( ! expB ) {
129 --expDiff;
130 sigExtra = 0;
131 if ( ! expDiff ) goto newlyAlignedABigger;
132 }
133 sig128 = softfloat_shiftRightJam128( sigB, 0, expDiff );
134 sigB = sig128.v64;
135 sigExtra = sig128.v0;
136 newlyAlignedABigger:
137 expZ = expA;
138 aBigger:
139 sig128 = softfloat_sub128( sigA, 0, sigB, sigExtra );
140 /*------------------------------------------------------------------------
141 *------------------------------------------------------------------------*/
142 normRoundPack:
143 return
144 softfloat_normRoundPackToExtF80(
145 signZ, expZ, sig128.v64, sig128.v0, extF80_roundingPrecision );
146 /*------------------------------------------------------------------------
147 *------------------------------------------------------------------------*/
148 propagateNaN:
149 uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 );
150 uiZ64 = uiZ.v64;
151 uiZ0 = uiZ.v0;
152 uiZ:
153 uZ.s.signExp = uiZ64;
154 uZ.s.signif = uiZ0;
155 return uZ.f;
156
157}
158
deps/SoftFloat-3e/source/s_subMagsF128.c deleted-139
...@@ -1,139 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float128_t
45 softfloat_subMagsF128(
46 uint_fast64_t uiA64,
47 uint_fast64_t uiA0,
48 uint_fast64_t uiB64,
49 uint_fast64_t uiB0,
50 bool signZ
51 )
52{
53 int_fast32_t expA;
54 struct uint128 sigA;
55 int_fast32_t expB;
56 struct uint128 sigB, sigZ;
57 int_fast32_t expDiff, expZ;
58 struct uint128 uiZ;
59 union ui128_f128 uZ;
60
61 expA = expF128UI64( uiA64 );
62 sigA.v64 = fracF128UI64( uiA64 );
63 sigA.v0 = uiA0;
64 expB = expF128UI64( uiB64 );
65 sigB.v64 = fracF128UI64( uiB64 );
66 sigB.v0 = uiB0;
67 sigA = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 4 );
68 sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 4 );
69 expDiff = expA - expB;
70 if ( 0 < expDiff ) goto expABigger;
71 if ( expDiff < 0 ) goto expBBigger;
72 if ( expA == 0x7FFF ) {
73 if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN;
74 softfloat_raiseFlags( softfloat_flag_invalid );
75 uiZ.v64 = defaultNaNF128UI64;
76 uiZ.v0 = defaultNaNF128UI0;
77 goto uiZ;
78 }
79 expZ = expA;
80 if ( ! expZ ) expZ = 1;
81 if ( sigB.v64 < sigA.v64 ) goto aBigger;
82 if ( sigA.v64 < sigB.v64 ) goto bBigger;
83 if ( sigB.v0 < sigA.v0 ) goto aBigger;
84 if ( sigA.v0 < sigB.v0 ) goto bBigger;
85 uiZ.v64 =
86 packToF128UI64(
87 (softfloat_roundingMode == softfloat_round_min), 0, 0 );
88 uiZ.v0 = 0;
89 goto uiZ;
90 expBBigger:
91 if ( expB == 0x7FFF ) {
92 if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
93 uiZ.v64 = packToF128UI64( signZ ^ 1, 0x7FFF, 0 );
94 uiZ.v0 = 0;
95 goto uiZ;
96 }
97 if ( expA ) {
98 sigA.v64 |= UINT64_C( 0x0010000000000000 );
99 } else {
100 ++expDiff;
101 if ( ! expDiff ) goto newlyAlignedBBigger;
102 }
103 sigA = softfloat_shiftRightJam128( sigA.v64, sigA.v0, -expDiff );
104 newlyAlignedBBigger:
105 expZ = expB;
106 sigB.v64 |= UINT64_C( 0x0010000000000000 );
107 bBigger:
108 signZ = ! signZ;
109 sigZ = softfloat_sub128( sigB.v64, sigB.v0, sigA.v64, sigA.v0 );
110 goto normRoundPack;
111 expABigger:
112 if ( expA == 0x7FFF ) {
113 if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
114 uiZ.v64 = uiA64;
115 uiZ.v0 = uiA0;
116 goto uiZ;
117 }
118 if ( expB ) {
119 sigB.v64 |= UINT64_C( 0x0010000000000000 );
120 } else {
121 --expDiff;
122 if ( ! expDiff ) goto newlyAlignedABigger;
123 }
124 sigB = softfloat_shiftRightJam128( sigB.v64, sigB.v0, expDiff );
125 newlyAlignedABigger:
126 expZ = expA;
127 sigA.v64 |= UINT64_C( 0x0010000000000000 );
128 aBigger:
129 sigZ = softfloat_sub128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 );
130 normRoundPack:
131 return softfloat_normRoundPackToF128( signZ, expZ - 5, sigZ.v64, sigZ.v0 );
132 propagateNaN:
133 uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
134 uiZ:
135 uZ.ui = uiZ;
136 return uZ.f;
137
138}
139
deps/SoftFloat-3e/source/s_subMagsF16.c deleted-187
...@@ -1,187 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
8University of California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float16_t softfloat_subMagsF16( uint_fast16_t uiA, uint_fast16_t uiB )
45{
46 int_fast8_t expA;
47 uint_fast16_t sigA;
48 int_fast8_t expB;
49 uint_fast16_t sigB;
50 int_fast8_t expDiff;
51 uint_fast16_t uiZ;
52 int_fast16_t sigDiff;
53 bool signZ;
54 int_fast8_t shiftDist, expZ;
55 uint_fast16_t sigZ, sigX, sigY;
56 uint_fast32_t sig32Z;
57 int_fast8_t roundingMode;
58 union ui16_f16 uZ;
59
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 expA = expF16UI( uiA );
63 sigA = fracF16UI( uiA );
64 expB = expF16UI( uiB );
65 sigB = fracF16UI( uiB );
66 /*------------------------------------------------------------------------
67 *------------------------------------------------------------------------*/
68 expDiff = expA - expB;
69 if ( ! expDiff ) {
70 /*--------------------------------------------------------------------
71 *--------------------------------------------------------------------*/
72 if ( expA == 0x1F ) {
73 if ( sigA | sigB ) goto propagateNaN;
74 softfloat_raiseFlags( softfloat_flag_invalid );
75 uiZ = defaultNaNF16UI;
76 goto uiZ;
77 }
78 sigDiff = sigA - sigB;
79 if ( ! sigDiff ) {
80 uiZ =
81 packToF16UI(
82 (softfloat_roundingMode == softfloat_round_min), 0, 0 );
83 goto uiZ;
84 }
85 if ( expA ) --expA;
86 signZ = signF16UI( uiA );
87 if ( sigDiff < 0 ) {
88 signZ = ! signZ;
89 sigDiff = -sigDiff;
90 }
91 shiftDist = softfloat_countLeadingZeros16( sigDiff ) - 5;
92 expZ = expA - shiftDist;
93 if ( expZ < 0 ) {
94 shiftDist = expA;
95 expZ = 0;
96 }
97 sigZ = sigDiff<<shiftDist;
98 goto pack;
99 } else {
100 /*--------------------------------------------------------------------
101 *--------------------------------------------------------------------*/
102 signZ = signF16UI( uiA );
103 if ( expDiff < 0 ) {
104 /*----------------------------------------------------------------
105 *----------------------------------------------------------------*/
106 signZ = ! signZ;
107 if ( expB == 0x1F ) {
108 if ( sigB ) goto propagateNaN;
109 uiZ = packToF16UI( signZ, 0x1F, 0 );
110 goto uiZ;
111 }
112 if ( expDiff <= -13 ) {
113 uiZ = packToF16UI( signZ, expB, sigB );
114 if ( expA | sigA ) goto subEpsilon;
115 goto uiZ;
116 }
117 expZ = expA + 19;
118 sigX = sigB | 0x0400;
119 sigY = sigA + (expA ? 0x0400 : sigA);
120 expDiff = -expDiff;
121 } else {
122 /*----------------------------------------------------------------
123 *----------------------------------------------------------------*/
124 uiZ = uiA;
125 if ( expA == 0x1F ) {
126 if ( sigA ) goto propagateNaN;
127 goto uiZ;
128 }
129 if ( 13 <= expDiff ) {
130 if ( expB | sigB ) goto subEpsilon;
131 goto uiZ;
132 }
133 expZ = expB + 19;
134 sigX = sigA | 0x0400;
135 sigY = sigB + (expB ? 0x0400 : sigB);
136 }
137 sig32Z = ((uint_fast32_t) sigX<<expDiff) - sigY;
138 shiftDist = softfloat_countLeadingZeros32( sig32Z ) - 1;
139 sig32Z <<= shiftDist;
140 expZ -= shiftDist;
141 sigZ = sig32Z>>16;
142 if ( sig32Z & 0xFFFF ) {
143 sigZ |= 1;
144 } else {
145 if ( ! (sigZ & 0xF) && ((unsigned int) expZ < 0x1E) ) {
146 sigZ >>= 4;
147 goto pack;
148 }
149 }
150 return softfloat_roundPackToF16( signZ, expZ, sigZ );
151 }
152 /*------------------------------------------------------------------------
153 *------------------------------------------------------------------------*/
154 propagateNaN:
155 uiZ = softfloat_propagateNaNF16UI( uiA, uiB );
156 goto uiZ;
157 /*------------------------------------------------------------------------
158 *------------------------------------------------------------------------*/
159 subEpsilon:
160 roundingMode = softfloat_roundingMode;
161 if ( roundingMode != softfloat_round_near_even ) {
162 if (
163 (roundingMode == softfloat_round_minMag)
164 || (roundingMode
165 == (signF16UI( uiZ ) ? softfloat_round_max
166 : softfloat_round_min))
167 ) {
168 --uiZ;
169 }
170#ifdef SOFTFLOAT_ROUND_ODD
171 else if ( roundingMode == softfloat_round_odd ) {
172 uiZ = (uiZ - 1) | 1;
173 }
174#endif
175 }
176 softfloat_exceptionFlags |= softfloat_flag_inexact;
177 goto uiZ;
178 /*------------------------------------------------------------------------
179 *------------------------------------------------------------------------*/
180 pack:
181 uiZ = packToF16UI( signZ, expZ, sigZ );
182 uiZ:
183 uZ.ui = uiZ;
184 return uZ.f;
185
186}
187
deps/SoftFloat-3e/source/s_subMagsF32.c deleted-143
...@@ -1,143 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float32_t softfloat_subMagsF32( uint_fast32_t uiA, uint_fast32_t uiB )
45{
46 int_fast16_t expA;
47 uint_fast32_t sigA;
48 int_fast16_t expB;
49 uint_fast32_t sigB;
50 int_fast16_t expDiff;
51 uint_fast32_t uiZ;
52 int_fast32_t sigDiff;
53 bool signZ;
54 int_fast8_t shiftDist;
55 int_fast16_t expZ;
56 uint_fast32_t sigX, sigY;
57 union ui32_f32 uZ;
58
59 /*------------------------------------------------------------------------
60 *------------------------------------------------------------------------*/
61 expA = expF32UI( uiA );
62 sigA = fracF32UI( uiA );
63 expB = expF32UI( uiB );
64 sigB = fracF32UI( uiB );
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 expDiff = expA - expB;
68 if ( ! expDiff ) {
69 /*--------------------------------------------------------------------
70 *--------------------------------------------------------------------*/
71 if ( expA == 0xFF ) {
72 if ( sigA | sigB ) goto propagateNaN;
73 softfloat_raiseFlags( softfloat_flag_invalid );
74 uiZ = defaultNaNF32UI;
75 goto uiZ;
76 }
77 sigDiff = sigA - sigB;
78 if ( ! sigDiff ) {
79 uiZ =
80 packToF32UI(
81 (softfloat_roundingMode == softfloat_round_min), 0, 0 );
82 goto uiZ;
83 }
84 if ( expA ) --expA;
85 signZ = signF32UI( uiA );
86 if ( sigDiff < 0 ) {
87 signZ = ! signZ;
88 sigDiff = -sigDiff;
89 }
90 shiftDist = softfloat_countLeadingZeros32( sigDiff ) - 8;
91 expZ = expA - shiftDist;
92 if ( expZ < 0 ) {
93 shiftDist = expA;
94 expZ = 0;
95 }
96 uiZ = packToF32UI( signZ, expZ, sigDiff<<shiftDist );
97 goto uiZ;
98 } else {
99 /*--------------------------------------------------------------------
100 *--------------------------------------------------------------------*/
101 signZ = signF32UI( uiA );
102 sigA <<= 7;
103 sigB <<= 7;
104 if ( expDiff < 0 ) {
105 /*----------------------------------------------------------------
106 *----------------------------------------------------------------*/
107 signZ = ! signZ;
108 if ( expB == 0xFF ) {
109 if ( sigB ) goto propagateNaN;
110 uiZ = packToF32UI( signZ, 0xFF, 0 );
111 goto uiZ;
112 }
113 expZ = expB - 1;
114 sigX = sigB | 0x40000000;
115 sigY = sigA + (expA ? 0x40000000 : sigA);
116 expDiff = -expDiff;
117 } else {
118 /*----------------------------------------------------------------
119 *----------------------------------------------------------------*/
120 if ( expA == 0xFF ) {
121 if ( sigA ) goto propagateNaN;
122 uiZ = uiA;
123 goto uiZ;
124 }
125 expZ = expA - 1;
126 sigX = sigA | 0x40000000;
127 sigY = sigB + (expB ? 0x40000000 : sigB);
128 }
129 return
130 softfloat_normRoundPackToF32(
131 signZ, expZ, sigX - softfloat_shiftRightJam32( sigY, expDiff )
132 );
133 }
134 /*------------------------------------------------------------------------
135 *------------------------------------------------------------------------*/
136 propagateNaN:
137 uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
138 uiZ:
139 uZ.ui = uiZ;
140 return uZ.f;
141
142}
143
deps/SoftFloat-3e/source/s_subMagsF64.c deleted-141
...@@ -1,141 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42#include "softfloat.h"
43
44float64_t
45 softfloat_subMagsF64( uint_fast64_t uiA, uint_fast64_t uiB, bool signZ )
46{
47 int_fast16_t expA;
48 uint_fast64_t sigA;
49 int_fast16_t expB;
50 uint_fast64_t sigB;
51 int_fast16_t expDiff;
52 uint_fast64_t uiZ;
53 int_fast64_t sigDiff;
54 int_fast8_t shiftDist;
55 int_fast16_t expZ;
56 uint_fast64_t sigZ;
57 union ui64_f64 uZ;
58
59 /*------------------------------------------------------------------------
60 *------------------------------------------------------------------------*/
61 expA = expF64UI( uiA );
62 sigA = fracF64UI( uiA );
63 expB = expF64UI( uiB );
64 sigB = fracF64UI( uiB );
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 expDiff = expA - expB;
68 if ( ! expDiff ) {
69 /*--------------------------------------------------------------------
70 *--------------------------------------------------------------------*/
71 if ( expA == 0x7FF ) {
72 if ( sigA | sigB ) goto propagateNaN;
73 softfloat_raiseFlags( softfloat_flag_invalid );
74 uiZ = defaultNaNF64UI;
75 goto uiZ;
76 }
77 sigDiff = sigA - sigB;
78 if ( ! sigDiff ) {
79 uiZ =
80 packToF64UI(
81 (softfloat_roundingMode == softfloat_round_min), 0, 0 );
82 goto uiZ;
83 }
84 if ( expA ) --expA;
85 if ( sigDiff < 0 ) {
86 signZ = ! signZ;
87 sigDiff = -sigDiff;
88 }
89 shiftDist = softfloat_countLeadingZeros64( sigDiff ) - 11;
90 expZ = expA - shiftDist;
91 if ( expZ < 0 ) {
92 shiftDist = expA;
93 expZ = 0;
94 }
95 uiZ = packToF64UI( signZ, expZ, sigDiff<<shiftDist );
96 goto uiZ;
97 } else {
98 /*--------------------------------------------------------------------
99 *--------------------------------------------------------------------*/
100 sigA <<= 10;
101 sigB <<= 10;
102 if ( expDiff < 0 ) {
103 /*----------------------------------------------------------------
104 *----------------------------------------------------------------*/
105 signZ = ! signZ;
106 if ( expB == 0x7FF ) {
107 if ( sigB ) goto propagateNaN;
108 uiZ = packToF64UI( signZ, 0x7FF, 0 );
109 goto uiZ;
110 }
111 sigA += expA ? UINT64_C( 0x4000000000000000 ) : sigA;
112 sigA = softfloat_shiftRightJam64( sigA, -expDiff );
113 sigB |= UINT64_C( 0x4000000000000000 );
114 expZ = expB;
115 sigZ = sigB - sigA;
116 } else {
117 /*----------------------------------------------------------------
118 *----------------------------------------------------------------*/
119 if ( expA == 0x7FF ) {
120 if ( sigA ) goto propagateNaN;
121 uiZ = uiA;
122 goto uiZ;
123 }
124 sigB += expB ? UINT64_C( 0x4000000000000000 ) : sigB;
125 sigB = softfloat_shiftRightJam64( sigB, expDiff );
126 sigA |= UINT64_C( 0x4000000000000000 );
127 expZ = expA;
128 sigZ = sigA - sigB;
129 }
130 return softfloat_normRoundPackToF64( signZ, expZ - 1, sigZ );
131 }
132 /*------------------------------------------------------------------------
133 *------------------------------------------------------------------------*/
134 propagateNaN:
135 uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
136 uiZ:
137 uZ.ui = uiZ;
138 return uZ.f;
139
140}
141
deps/SoftFloat-3e/source/s_tryPropagateNaNExtF80M.c deleted-64
...@@ -1,64 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include "platform.h"
39#include "internals.h"
40#include "specialize.h"
41
42bool
43 softfloat_tryPropagateNaNExtF80M(
44 const struct extFloat80M *aSPtr,
45 const struct extFloat80M *bSPtr,
46 struct extFloat80M *zSPtr
47 )
48{
49 uint_fast16_t ui64;
50 uint64_t ui0;
51
52 ui64 = aSPtr->signExp;
53 ui0 = aSPtr->signif;
54 if ( isNaNExtF80UI( ui64, ui0 ) ) goto propagateNaN;
55 ui64 = bSPtr->signExp;
56 ui0 = bSPtr->signif;
57 if ( isNaNExtF80UI( ui64, ui0 ) ) goto propagateNaN;
58 return false;
59 propagateNaN:
60 softfloat_propagateNaNExtF80M( aSPtr, bSPtr, zSPtr );
61 return true;
62
63}
64
deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c deleted-55
...@@ -1,55 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "specialize.h"
42
43bool
44 softfloat_tryPropagateNaNF128M(
45 const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr )
46{
47
48 if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) {
49 softfloat_propagateNaNF128M( aWPtr, bWPtr, zWPtr );
50 return true;
51 }
52 return false;
53
54}
55
deps/SoftFloat-3e/source/softfloat_state.c deleted-52
...@@ -1,52 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "specialize.h"
41#include "softfloat.h"
42
43#ifndef THREAD_LOCAL
44#define THREAD_LOCAL
45#endif
46
47THREAD_LOCAL uint_fast8_t softfloat_roundingMode = softfloat_round_near_even;
48THREAD_LOCAL uint_fast8_t softfloat_detectTininess = init_detectTininess;
49THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags = 0;
50
51THREAD_LOCAL uint_fast8_t extF80_roundingPrecision = 80;
52
deps/SoftFloat-3e/source/ui32_to_extF80.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42extFloat80_t ui32_to_extF80( uint32_t a )
43{
44 uint_fast16_t uiZ64;
45 int_fast8_t shiftDist;
46 union { struct extFloat80M s; extFloat80_t f; } uZ;
47
48 uiZ64 = 0;
49 if ( a ) {
50 shiftDist = softfloat_countLeadingZeros32( a );
51 uiZ64 = 0x401E - shiftDist;
52 a <<= shiftDist;
53 }
54 uZ.s.signExp = uiZ64;
55 uZ.s.signif = (uint_fast64_t) a<<32;
56 return uZ.f;
57
58}
59
deps/SoftFloat-3e/source/ui32_to_extF80M.c deleted-74
...@@ -1,74 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42#ifdef SOFTFLOAT_FAST_INT64
43
44void ui32_to_extF80M( uint32_t a, extFloat80_t *zPtr )
45{
46
47 *zPtr = ui32_to_extF80( a );
48
49}
50
51#else
52
53void ui32_to_extF80M( uint32_t a, extFloat80_t *zPtr )
54{
55 struct extFloat80M *zSPtr;
56 uint_fast16_t uiZ64;
57 uint64_t sigZ;
58 int_fast8_t shiftDist;
59
60 zSPtr = (struct extFloat80M *) zPtr;
61 uiZ64 = 0;
62 sigZ = 0;
63 if ( a ) {
64 shiftDist = softfloat_countLeadingZeros32( a );
65 uiZ64 = packToExtF80UI64( 0, 0x401E - shiftDist );
66 sigZ = (uint64_t) (a<<shiftDist)<<32;
67 }
68 zSPtr->signExp = uiZ64;
69 zSPtr->signif = sigZ;
70
71}
72
73#endif
74
deps/SoftFloat-3e/source/ui32_to_f128.c deleted-60
...@@ -1,60 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float128_t ui32_to_f128( uint32_t a )
43{
44 uint_fast64_t uiZ64;
45 int_fast8_t shiftDist;
46 union ui128_f128 uZ;
47
48 uiZ64 = 0;
49 if ( a ) {
50 shiftDist = softfloat_countLeadingZeros32( a ) + 17;
51 uiZ64 =
52 packToF128UI64(
53 0, 0x402E - shiftDist, (uint_fast64_t) a<<shiftDist );
54 }
55 uZ.ui.v64 = uiZ64;
56 uZ.ui.v0 = 0;
57 return uZ.f;
58
59}
60
deps/SoftFloat-3e/source/ui32_to_f128M.c deleted-76
...@@ -1,76 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42#ifdef SOFTFLOAT_FAST_INT64
43
44void ui32_to_f128M( uint32_t a, float128_t *zPtr )
45{
46
47 *zPtr = ui32_to_f128( a );
48
49}
50
51#else
52
53void ui32_to_f128M( uint32_t a, float128_t *zPtr )
54{
55 uint32_t *zWPtr, uiZ96, uiZ64;
56 int_fast8_t shiftDist;
57 uint64_t normA;
58
59 zWPtr = (uint32_t *) zPtr;
60 uiZ96 = 0;
61 uiZ64 = 0;
62 if ( a ) {
63 shiftDist = softfloat_countLeadingZeros32( a ) + 17;
64 normA = (uint64_t) a<<shiftDist;
65 uiZ96 = packToF128UI96( 0, 0x402E - shiftDist, normA>>32 );
66 uiZ64 = normA;
67 }
68 zWPtr[indexWord( 4, 3 )] = uiZ96;
69 zWPtr[indexWord( 4, 2 )] = uiZ64;
70 zWPtr[indexWord( 4, 1 )] = 0;
71 zWPtr[indexWord( 4, 0 )] = 0;
72
73}
74
75#endif
76
deps/SoftFloat-3e/source/ui32_to_f16.c deleted-65
...@@ -1,65 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float16_t ui32_to_f16( uint32_t a )
43{
44 int_fast8_t shiftDist;
45 union ui16_f16 u;
46 uint_fast16_t sig;
47
48 shiftDist = softfloat_countLeadingZeros32( a ) - 21;
49 if ( 0 <= shiftDist ) {
50 u.ui =
51 a ? packToF16UI(
52 0, 0x18 - shiftDist, (uint_fast16_t) a<<shiftDist )
53 : 0;
54 return u.f;
55 } else {
56 shiftDist += 4;
57 sig =
58 (shiftDist < 0)
59 ? a>>(-shiftDist) | ((uint32_t) (a<<(shiftDist & 31)) != 0)
60 : (uint_fast16_t) a<<shiftDist;
61 return softfloat_roundPackToF16( 0, 0x1C - shiftDist, sig );
62 }
63
64}
65
deps/SoftFloat-3e/source/ui32_to_f32.c deleted-57
...@@ -1,57 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float32_t ui32_to_f32( uint32_t a )
43{
44 union ui32_f32 uZ;
45
46 if ( ! a ) {
47 uZ.ui = 0;
48 return uZ.f;
49 }
50 if ( a & 0x80000000 ) {
51 return softfloat_roundPackToF32( 0, 0x9D, a>>1 | (a & 1) );
52 } else {
53 return softfloat_normRoundPackToF32( 0, 0x9C, a );
54 }
55
56}
57
deps/SoftFloat-3e/source/ui32_to_f64.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float64_t ui32_to_f64( uint32_t a )
43{
44 uint_fast64_t uiZ;
45 int_fast8_t shiftDist;
46 union ui64_f64 uZ;
47
48 if ( ! a ) {
49 uiZ = 0;
50 } else {
51 shiftDist = softfloat_countLeadingZeros32( a ) + 21;
52 uiZ =
53 packToF64UI( 0, 0x432 - shiftDist, (uint_fast64_t) a<<shiftDist );
54 }
55 uZ.ui = uiZ;
56 return uZ.f;
57
58}
59
deps/SoftFloat-3e/source/ui64_to_extF80.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42extFloat80_t ui64_to_extF80( uint64_t a )
43{
44 uint_fast16_t uiZ64;
45 int_fast8_t shiftDist;
46 union { struct extFloat80M s; extFloat80_t f; } uZ;
47
48 uiZ64 = 0;
49 if ( a ) {
50 shiftDist = softfloat_countLeadingZeros64( a );
51 uiZ64 = 0x403E - shiftDist;
52 a <<= shiftDist;
53 }
54 uZ.s.signExp = uiZ64;
55 uZ.s.signif = a;
56 return uZ.f;
57
58}
59
deps/SoftFloat-3e/source/ui64_to_extF80M.c deleted-74
...@@ -1,74 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42#ifdef SOFTFLOAT_FAST_INT64
43
44void ui64_to_extF80M( uint64_t a, extFloat80_t *zPtr )
45{
46
47 *zPtr = ui64_to_extF80( a );
48
49}
50
51#else
52
53void ui64_to_extF80M( uint64_t a, extFloat80_t *zPtr )
54{
55 struct extFloat80M *zSPtr;
56 uint_fast16_t uiZ64;
57 uint64_t sigZ;
58 int_fast8_t shiftDist;
59
60 zSPtr = (struct extFloat80M *) zPtr;
61 uiZ64 = 0;
62 sigZ = 0;
63 if ( a ) {
64 shiftDist = softfloat_countLeadingZeros64( a );
65 uiZ64 = packToExtF80UI64( 0, 0x403E - shiftDist );
66 sigZ = a<<shiftDist;
67 }
68 zSPtr->signExp = uiZ64;
69 zSPtr->signif = sigZ;
70
71}
72
73#endif
74
deps/SoftFloat-3e/source/ui64_to_f128.c deleted-68
...@@ -1,68 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float128_t ui64_to_f128( uint64_t a )
43{
44 uint_fast64_t uiZ64, uiZ0;
45 int_fast8_t shiftDist;
46 struct uint128 zSig;
47 union ui128_f128 uZ;
48
49 if ( ! a ) {
50 uiZ64 = 0;
51 uiZ0 = 0;
52 } else {
53 shiftDist = softfloat_countLeadingZeros64( a ) + 49;
54 if ( 64 <= shiftDist ) {
55 zSig.v64 = a<<(shiftDist - 64);
56 zSig.v0 = 0;
57 } else {
58 zSig = softfloat_shortShiftLeft128( 0, a, shiftDist );
59 }
60 uiZ64 = packToF128UI64( 0, 0x406E - shiftDist, zSig.v64 );
61 uiZ0 = zSig.v0;
62 }
63 uZ.ui.v64 = uiZ64;
64 uZ.ui.v0 = uiZ0;
65 return uZ.f;
66
67}
68
deps/SoftFloat-3e/source/ui64_to_f128M.c deleted-86
...@@ -1,86 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42#ifdef SOFTFLOAT_FAST_INT64
43
44void ui64_to_f128M( uint64_t a, float128_t *zPtr )
45{
46
47 *zPtr = ui64_to_f128( a );
48
49}
50
51#else
52
53void ui64_to_f128M( uint64_t a, float128_t *zPtr )
54{
55 uint32_t *zWPtr, uiZ96, uiZ64;
56 uint_fast8_t shiftDist;
57 uint32_t *ptr;
58
59 zWPtr = (uint32_t *) zPtr;
60 uiZ96 = 0;
61 uiZ64 = 0;
62 zWPtr[indexWord( 4, 1 )] = 0;
63 zWPtr[indexWord( 4, 0 )] = 0;
64 if ( a ) {
65 shiftDist = softfloat_countLeadingZeros64( a ) + 17;
66 if ( shiftDist < 32 ) {
67 ptr = zWPtr + indexMultiwordHi( 4, 3 );
68 ptr[indexWord( 3, 2 )] = 0;
69 ptr[indexWord( 3, 1 )] = a>>32;
70 ptr[indexWord( 3, 0 )] = a;
71 softfloat_shortShiftLeft96M( ptr, shiftDist, ptr );
72 ptr[indexWordHi( 3 )] =
73 packToF128UI96( 0, 0x404E - shiftDist, ptr[indexWordHi( 3 )] );
74 return;
75 }
76 a <<= shiftDist - 32;
77 uiZ96 = packToF128UI96( 0, 0x404E - shiftDist, a>>32 );
78 uiZ64 = a;
79 }
80 zWPtr[indexWord( 4, 3 )] = uiZ96;
81 zWPtr[indexWord( 4, 2 )] = uiZ64;
82
83}
84
85#endif
86
deps/SoftFloat-3e/source/ui64_to_f16.c deleted-64
...@@ -1,64 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float16_t ui64_to_f16( uint64_t a )
43{
44 int_fast8_t shiftDist;
45 union ui16_f16 u;
46 uint_fast16_t sig;
47
48 shiftDist = softfloat_countLeadingZeros64( a ) - 53;
49 if ( 0 <= shiftDist ) {
50 u.ui =
51 a ? packToF16UI(
52 0, 0x18 - shiftDist, (uint_fast16_t) a<<shiftDist )
53 : 0;
54 return u.f;
55 } else {
56 shiftDist += 4;
57 sig =
58 (shiftDist < 0) ? softfloat_shortShiftRightJam64( a, -shiftDist )
59 : (uint_fast16_t) a<<shiftDist;
60 return softfloat_roundPackToF16( 0, 0x1C - shiftDist, sig );
61 }
62
63}
64
deps/SoftFloat-3e/source/ui64_to_f32.c deleted-64
...@@ -1,64 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8California. All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float32_t ui64_to_f32( uint64_t a )
43{
44 int_fast8_t shiftDist;
45 union ui32_f32 u;
46 uint_fast32_t sig;
47
48 shiftDist = softfloat_countLeadingZeros64( a ) - 40;
49 if ( 0 <= shiftDist ) {
50 u.ui =
51 a ? packToF32UI(
52 0, 0x95 - shiftDist, (uint_fast32_t) a<<shiftDist )
53 : 0;
54 return u.f;
55 } else {
56 shiftDist += 7;
57 sig =
58 (shiftDist < 0) ? softfloat_shortShiftRightJam64( a, -shiftDist )
59 : (uint_fast32_t) a<<shiftDist;
60 return softfloat_roundPackToF32( 0, 0x9C - shiftDist, sig );
61 }
62
63}
64
deps/SoftFloat-3e/source/ui64_to_f64.c deleted-59
...@@ -1,59 +0,0 @@
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
8All Rights Reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdint.h>
38#include "platform.h"
39#include "internals.h"
40#include "softfloat.h"
41
42float64_t ui64_to_f64( uint64_t a )
43{
44 union ui64_f64 uZ;
45
46 if ( ! a ) {
47 uZ.ui = 0;
48 return uZ.f;
49 }
50 if ( a & UINT64_C( 0x8000000000000000 ) ) {
51 return
52 softfloat_roundPackToF64(
53 0, 0x43D, softfloat_shortShiftRightJam64( a, 1 ) );
54 } else {
55 return softfloat_normRoundPackToF64( 0, 0x43C, a );
56 }
57
58}
59
src/Compilation.zig-194
...@@ -30,7 +30,6 @@ const fatal = @import("main.zig").fatal;...@@ -30,7 +30,6 @@ const fatal = @import("main.zig").fatal;
30const clangMain = @import("main.zig").clangMain;30const clangMain = @import("main.zig").clangMain;
31const Module = @import("Module.zig");31const Module = @import("Module.zig");
32const Cache = @import("Cache.zig");32const Cache = @import("Cache.zig");
33const stage1 = @import("stage1.zig");
34const translate_c = @import("translate_c.zig");33const translate_c = @import("translate_c.zig");
35const c_codegen = @import("codegen/c.zig");34const c_codegen = @import("codegen/c.zig");
36const ThreadPool = @import("ThreadPool.zig");35const ThreadPool = @import("ThreadPool.zig");
...@@ -5411,199 +5410,6 @@ fn buildOutputFromZig(...@@ -5411,199 +5410,6 @@ fn buildOutputFromZig(
5411 };5410 };
5412}5411}
54135412
5414fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node) !void {
5415 const tracy_trace = trace(@src());
5416 defer tracy_trace.end();
5417
5418 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
5419 defer arena_allocator.deinit();
5420 const arena = arena_allocator.allocator();
5421
5422 // Here we use the legacy stage1 C++ compiler to compile Zig code.
5423 const mod = comp.bin_file.options.module.?;
5424 const directory = mod.zig_cache_artifact_directory; // Just an alias to make it shorter to type.
5425 const main_zig_file = try mod.main_pkg.root_src_directory.join(arena, &[_][]const u8{
5426 mod.main_pkg.root_src_path,
5427 });
5428 const zig_lib_dir = comp.zig_lib_directory.path.?;
5429 const target = comp.getTarget();
5430
5431 // The include_compiler_rt stored in the bin file options here means that we need
5432 // compiler-rt symbols *somehow*. However, in the context of using the stage1 backend
5433 // we need to tell stage1 to include compiler-rt only if stage1 is the place that
5434 // needs to provide those symbols. Otherwise the stage2 infrastructure will take care
5435 // of it in the linker, by putting compiler_rt.o into a static archive, or linking
5436 // compiler_rt.a against an executable. In other words we only want to set this flag
5437 // for stage1 if we are using build-obj.
5438 const include_compiler_rt = comp.bin_file.options.output_mode == .Obj and
5439 comp.bin_file.options.include_compiler_rt;
5440
5441 const stage2_target = try arena.create(stage1.Stage2Target);
5442 stage2_target.* = .{
5443 .arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch
5444 .os = @enumToInt(target.os.tag),
5445 .abi = @enumToInt(target.abi),
5446 .is_native_os = comp.bin_file.options.is_native_os,
5447 .is_native_cpu = false, // Only true when bootstrapping the compiler.
5448 .llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null,
5449 .llvm_cpu_features = comp.bin_file.options.llvm_cpu_features.?,
5450 .llvm_target_abi = if (target_util.llvmMachineAbi(target)) |s| s.ptr else null,
5451 };
5452
5453 const main_pkg_path = mod.main_pkg.root_src_directory.path orelse "";
5454 const builtin_pkg = mod.main_pkg.table.get("builtin").?;
5455 const builtin_zig_path = try builtin_pkg.root_src_directory.join(arena, &.{builtin_pkg.root_src_path});
5456
5457 const stage1_module = stage1.create(
5458 @enumToInt(comp.bin_file.options.optimize_mode),
5459 main_pkg_path.ptr,
5460 main_pkg_path.len,
5461 main_zig_file.ptr,
5462 main_zig_file.len,
5463 zig_lib_dir.ptr,
5464 zig_lib_dir.len,
5465 stage2_target,
5466 comp.bin_file.options.is_test,
5467 ) orelse return error.OutOfMemory;
5468
5469 const emit_bin_path = if (comp.bin_file.options.emit != null) blk: {
5470 const obj_basename = try std.zig.binNameAlloc(arena, .{
5471 .root_name = comp.bin_file.options.root_name,
5472 .target = target,
5473 .output_mode = .Obj,
5474 });
5475 break :blk try directory.join(arena, &[_][]const u8{obj_basename});
5476 } else "";
5477
5478 if (mod.emit_h != null) {
5479 log.warn("-femit-h is not available in the stage1 backend; no .h file will be produced", .{});
5480 }
5481 const emit_h_loc: ?EmitLoc = if (mod.emit_h) |emit_h| emit_h.loc else null;
5482 const emit_h_path = try stage1LocPath(arena, emit_h_loc, directory);
5483 const emit_asm_path = try stage1LocPath(arena, comp.emit_asm, directory);
5484 const emit_llvm_ir_path = try stage1LocPath(arena, comp.emit_llvm_ir, directory);
5485 const emit_llvm_bc_path = try stage1LocPath(arena, comp.emit_llvm_bc, directory);
5486 const stage1_pkg = try createStage1Pkg(arena, "root", mod.main_pkg, null);
5487 const test_filter = comp.test_filter orelse ""[0..0];
5488 const test_name_prefix = comp.test_name_prefix orelse ""[0..0];
5489 const subsystem = if (comp.bin_file.options.subsystem) |s|
5490 @intToEnum(stage1.TargetSubsystem, @enumToInt(s))
5491 else
5492 stage1.TargetSubsystem.Auto;
5493 stage1_module.* = .{
5494 .root_name_ptr = comp.bin_file.options.root_name.ptr,
5495 .root_name_len = comp.bin_file.options.root_name.len,
5496 .emit_o_ptr = emit_bin_path.ptr,
5497 .emit_o_len = emit_bin_path.len,
5498 .emit_h_ptr = emit_h_path.ptr,
5499 .emit_h_len = emit_h_path.len,
5500 .emit_asm_ptr = emit_asm_path.ptr,
5501 .emit_asm_len = emit_asm_path.len,
5502 .emit_llvm_ir_ptr = emit_llvm_ir_path.ptr,
5503 .emit_llvm_ir_len = emit_llvm_ir_path.len,
5504 .emit_bitcode_ptr = emit_llvm_bc_path.ptr,
5505 .emit_bitcode_len = emit_llvm_bc_path.len,
5506 .builtin_zig_path_ptr = builtin_zig_path.ptr,
5507 .builtin_zig_path_len = builtin_zig_path.len,
5508 .test_filter_ptr = test_filter.ptr,
5509 .test_filter_len = test_filter.len,
5510 .test_name_prefix_ptr = test_name_prefix.ptr,
5511 .test_name_prefix_len = test_name_prefix.len,
5512 .userdata = @ptrToInt(comp),
5513 .main_pkg = stage1_pkg,
5514 .code_model = @enumToInt(comp.bin_file.options.machine_code_model),
5515 .subsystem = subsystem,
5516 .err_color = @enumToInt(comp.color),
5517 .pic = comp.bin_file.options.pic,
5518 .pie = comp.bin_file.options.pie,
5519 .lto = comp.bin_file.options.lto,
5520 .unwind_tables = comp.unwind_tables,
5521 .link_libc = comp.bin_file.options.link_libc,
5522 .link_libcpp = comp.bin_file.options.link_libcpp,
5523 .strip = comp.bin_file.options.strip,
5524 .is_single_threaded = comp.bin_file.options.single_threaded,
5525 .dll_export_fns = comp.bin_file.options.dll_export_fns,
5526 .link_mode_dynamic = comp.bin_file.options.link_mode == .Dynamic,
5527 .valgrind_enabled = comp.bin_file.options.valgrind,
5528 .tsan_enabled = comp.bin_file.options.tsan,
5529 .function_sections = comp.bin_file.options.function_sections,
5530 .include_compiler_rt = include_compiler_rt,
5531 .enable_stack_probing = comp.bin_file.options.stack_check,
5532 .red_zone = comp.bin_file.options.red_zone,
5533 .omit_frame_pointer = comp.bin_file.options.omit_frame_pointer,
5534 .enable_time_report = comp.time_report,
5535 .enable_stack_report = comp.stack_report,
5536 .test_is_evented = comp.test_evented_io,
5537 .verbose_ir = comp.verbose_air,
5538 .verbose_llvm_ir = comp.verbose_llvm_ir,
5539 .verbose_cimport = comp.verbose_cimport,
5540 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
5541 .main_progress_node = main_progress_node,
5542 .have_c_main = false,
5543 .have_winmain = false,
5544 .have_wwinmain = false,
5545 .have_winmain_crt_startup = false,
5546 .have_wwinmain_crt_startup = false,
5547 .have_dllmain_crt_startup = false,
5548 };
5549
5550 stage1_module.build_object();
5551
5552 mod.stage1_flags = .{
5553 .have_c_main = stage1_module.have_c_main,
5554 .have_winmain = stage1_module.have_winmain,
5555 .have_wwinmain = stage1_module.have_wwinmain,
5556 .have_winmain_crt_startup = stage1_module.have_winmain_crt_startup,
5557 .have_wwinmain_crt_startup = stage1_module.have_wwinmain_crt_startup,
5558 .have_dllmain_crt_startup = stage1_module.have_dllmain_crt_startup,
5559 };
5560
5561 stage1_module.destroy();
5562}
5563
5564fn stage1LocPath(arena: Allocator, opt_loc: ?EmitLoc, cache_directory: Directory) ![]const u8 {
5565 const loc = opt_loc orelse return "";
5566 const directory = loc.directory orelse cache_directory;
5567 return directory.join(arena, &[_][]const u8{loc.basename});
5568}
5569
5570fn createStage1Pkg(
5571 arena: Allocator,
5572 name: []const u8,
5573 pkg: *Package,
5574 parent_pkg: ?*stage1.Pkg,
5575) error{OutOfMemory}!*stage1.Pkg {
5576 const child_pkg = try arena.create(stage1.Pkg);
5577
5578 const pkg_children = blk: {
5579 var children = std.ArrayList(*stage1.Pkg).init(arena);
5580 var it = pkg.table.iterator();
5581 while (it.next()) |entry| {
5582 if (mem.eql(u8, entry.key_ptr.*, "std") or
5583 mem.eql(u8, entry.key_ptr.*, "builtin") or
5584 mem.eql(u8, entry.key_ptr.*, "root"))
5585 {
5586 continue;
5587 }
5588 try children.append(try createStage1Pkg(arena, entry.key_ptr.*, entry.value_ptr.*, child_pkg));
5589 }
5590 break :blk children.items;
5591 };
5592
5593 const src_path = try pkg.root_src_directory.join(arena, &[_][]const u8{pkg.root_src_path});
5594
5595 child_pkg.* = .{
5596 .name_ptr = name.ptr,
5597 .name_len = name.len,
5598 .path_ptr = src_path.ptr,
5599 .path_len = src_path.len,
5600 .children_ptr = pkg_children.ptr,
5601 .children_len = pkg_children.len,
5602 .parent = parent_pkg,
5603 };
5604 return child_pkg;
5605}
5606
5607pub fn build_crt_file(5413pub fn build_crt_file(
5608 comp: *Compilation,5414 comp: *Compilation,
5609 root_name: []const u8,5415 root_name: []const u8,
src/stage1.zig deleted-479
...@@ -1,479 +0,0 @@
1//! This is the main entry point for the Zig/C++ hybrid compiler (stage1).
2//! It has the functions exported from Zig, called in C++, and bindings for
3//! the functions exported from C++, called from Zig.
4
5const std = @import("std");
6const assert = std.debug.assert;
7const mem = std.mem;
8const CrossTarget = std.zig.CrossTarget;
9const Target = std.Target;
10const builtin = @import("builtin");
11
12const build_options = @import("build_options");
13const stage2 = @import("main.zig");
14const fatal = stage2.fatal;
15const Compilation = @import("Compilation.zig");
16const translate_c = @import("translate_c.zig");
17const target_util = @import("target.zig");
18
19comptime {
20 assert(builtin.link_libc);
21 assert(build_options.have_stage1);
22 assert(build_options.have_llvm);
23 if (!builtin.is_test) {
24 @export(main, .{ .name = "main" });
25 }
26}
27
28pub const log = stage2.log;
29pub const log_level = stage2.log_level;
30
31pub fn main(argc: c_int, argv: [*][*:0]u8) callconv(.C) c_int {
32 std.os.argv = argv[0..@intCast(usize, argc)];
33
34 std.debug.maybeEnableSegfaultHandler();
35
36 zig_stage1_os_init();
37
38 const gpa = std.heap.c_allocator;
39 var arena_instance = std.heap.ArenaAllocator.init(gpa);
40 defer arena_instance.deinit();
41 const arena = arena_instance.allocator();
42
43 const args: []const []const u8 = args: {
44 if (builtin.os.tag == .windows) {
45 break :args std.process.argsAlloc(arena) catch fatal("{s}", .{"OutOfMemory"});
46 } else {
47 const args = arena.alloc([]const u8, @intCast(usize, argc)) catch fatal("{s}", .{"OutOfMemory"});
48 for (args) |*arg, i| {
49 arg.* = mem.sliceTo(argv[i], 0);
50 }
51 break :args args;
52 }
53 };
54
55 if (builtin.mode == .Debug) {
56 stage2.mainArgs(gpa, arena, args) catch unreachable;
57 } else {
58 stage2.mainArgs(gpa, arena, args) catch |err| fatal("{s}", .{@errorName(err)});
59 }
60 return 0;
61}
62
63/// Matches stage2.Color;
64pub const ErrColor = c_int;
65/// Matches std.builtin.CodeModel
66pub const CodeModel = c_int;
67/// Matches std.Target.Os.Tag
68pub const OS = c_int;
69/// Matches std.builtin.BuildMode
70pub const BuildMode = c_int;
71
72pub const TargetSubsystem = enum(c_int) {
73 Console,
74 Windows,
75 Posix,
76 Native,
77 EfiApplication,
78 EfiBootServiceDriver,
79 EfiRom,
80 EfiRuntimeDriver,
81 Auto,
82};
83
84pub const Pkg = extern struct {
85 name_ptr: [*]const u8,
86 name_len: usize,
87 path_ptr: [*]const u8,
88 path_len: usize,
89 children_ptr: [*]*Pkg,
90 children_len: usize,
91 parent: ?*Pkg,
92};
93
94pub const Module = extern struct {
95 root_name_ptr: [*]const u8,
96 root_name_len: usize,
97 emit_o_ptr: [*]const u8,
98 emit_o_len: usize,
99 emit_h_ptr: [*]const u8,
100 emit_h_len: usize,
101 emit_asm_ptr: [*]const u8,
102 emit_asm_len: usize,
103 emit_llvm_ir_ptr: [*]const u8,
104 emit_llvm_ir_len: usize,
105 emit_bitcode_ptr: [*]const u8,
106 emit_bitcode_len: usize,
107 builtin_zig_path_ptr: [*]const u8,
108 builtin_zig_path_len: usize,
109 test_filter_ptr: [*]const u8,
110 test_filter_len: usize,
111 test_name_prefix_ptr: [*]const u8,
112 test_name_prefix_len: usize,
113 userdata: usize,
114 main_pkg: *Pkg,
115 main_progress_node: ?*std.Progress.Node,
116 code_model: CodeModel,
117 subsystem: TargetSubsystem,
118 err_color: ErrColor,
119 pic: bool,
120 pie: bool,
121 lto: bool,
122 unwind_tables: bool,
123 link_libc: bool,
124 link_libcpp: bool,
125 strip: bool,
126 is_single_threaded: bool,
127 dll_export_fns: bool,
128 link_mode_dynamic: bool,
129 valgrind_enabled: bool,
130 tsan_enabled: bool,
131 function_sections: bool,
132 include_compiler_rt: bool,
133 enable_stack_probing: bool,
134 red_zone: bool,
135 omit_frame_pointer: bool,
136 enable_time_report: bool,
137 enable_stack_report: bool,
138 test_is_evented: bool,
139 verbose_ir: bool,
140 verbose_llvm_ir: bool,
141 verbose_cimport: bool,
142 verbose_llvm_cpu_features: bool,
143
144 // Set by stage1
145 have_c_main: bool,
146 have_winmain: bool,
147 have_wwinmain: bool,
148 have_winmain_crt_startup: bool,
149 have_wwinmain_crt_startup: bool,
150 have_dllmain_crt_startup: bool,
151
152 pub fn build_object(mod: *Module) void {
153 zig_stage1_build_object(mod);
154 }
155
156 pub fn destroy(mod: *Module) void {
157 zig_stage1_destroy(mod);
158 }
159};
160
161pub const os_init = zig_stage1_os_init;
162extern fn zig_stage1_os_init() void;
163
164pub const create = zig_stage1_create;
165extern fn zig_stage1_create(
166 optimize_mode: BuildMode,
167 main_pkg_path_ptr: [*]const u8,
168 main_pkg_path_len: usize,
169 root_src_path_ptr: [*]const u8,
170 root_src_path_len: usize,
171 zig_lib_dir_ptr: [*c]const u8,
172 zig_lib_dir_len: usize,
173 target: [*c]const Stage2Target,
174 is_test_build: bool,
175) ?*Module;
176
177extern fn zig_stage1_build_object(*Module) void;
178extern fn zig_stage1_destroy(*Module) void;
179
180// ABI warning
181export fn stage2_panic(ptr: [*]const u8, len: usize) void {
182 @panic(ptr[0..len]);
183}
184
185// ABI warning
186const Error = enum(c_int) {
187 None,
188 OutOfMemory,
189 InvalidFormat,
190 SemanticAnalyzeFail,
191 AccessDenied,
192 Interrupted,
193 SystemResources,
194 FileNotFound,
195 FileSystem,
196 FileTooBig,
197 DivByZero,
198 Overflow,
199 PathAlreadyExists,
200 Unexpected,
201 ExactDivRemainder,
202 NegativeDenominator,
203 ShiftedOutOneBits,
204 CCompileErrors,
205 EndOfFile,
206 IsDir,
207 NotDir,
208 UnsupportedOperatingSystem,
209 SharingViolation,
210 PipeBusy,
211 PrimitiveTypeNotFound,
212 CacheUnavailable,
213 PathTooLong,
214 CCompilerCannotFindFile,
215 NoCCompilerInstalled,
216 ReadingDepFile,
217 InvalidDepFile,
218 MissingArchitecture,
219 MissingOperatingSystem,
220 UnknownArchitecture,
221 UnknownOperatingSystem,
222 UnknownABI,
223 InvalidFilename,
224 DiskQuota,
225 DiskSpace,
226 UnexpectedWriteFailure,
227 UnexpectedSeekFailure,
228 UnexpectedFileTruncationFailure,
229 Unimplemented,
230 OperationAborted,
231 BrokenPipe,
232 NoSpaceLeft,
233 NotLazy,
234 IsAsync,
235 ImportOutsidePkgPath,
236 UnknownCpuModel,
237 UnknownCpuFeature,
238 InvalidCpuFeatures,
239 InvalidLlvmCpuFeaturesFormat,
240 UnknownApplicationBinaryInterface,
241 ASTUnitFailure,
242 BadPathName,
243 SymLinkLoop,
244 ProcessFdQuotaExceeded,
245 SystemFdQuotaExceeded,
246 NoDevice,
247 DeviceBusy,
248 UnableToSpawnCCompiler,
249 CCompilerExitCode,
250 CCompilerCrashed,
251 CCompilerCannotFindHeaders,
252 LibCRuntimeNotFound,
253 LibCStdLibHeaderNotFound,
254 LibCKernel32LibNotFound,
255 UnsupportedArchitecture,
256 WindowsSdkNotFound,
257 UnknownDynamicLinkerPath,
258 TargetHasNoDynamicLinker,
259 InvalidAbiVersion,
260 InvalidOperatingSystemVersion,
261 UnknownClangOption,
262 NestedResponseFile,
263 ZigIsTheCCompiler,
264 FileBusy,
265 Locked,
266 InvalidCharacter,
267 UnicodePointTooLarge,
268};
269
270// ABI warning
271export fn stage2_version_string() [*:0]const u8 {
272 return build_options.version;
273}
274
275// ABI warning
276export fn stage2_version() Stage2SemVer {
277 return .{
278 .major = build_options.semver.major,
279 .minor = build_options.semver.minor,
280 .patch = build_options.semver.patch,
281 };
282}
283
284// ABI warning
285export fn stage2_attach_segfault_handler() void {
286 if (std.debug.runtime_safety and std.debug.have_segfault_handling_support) {
287 std.debug.attachSegfaultHandler();
288 }
289}
290
291// ABI warning
292export fn stage2_progress_create() *std.Progress {
293 const ptr = std.heap.c_allocator.create(std.Progress) catch @panic("out of memory");
294 // If the terminal is dumb, we dont want to show the user all the
295 // output.
296 ptr.* = std.Progress{ .dont_print_on_dumb = true };
297 return ptr;
298}
299
300// ABI warning
301export fn stage2_progress_destroy(progress: *std.Progress) void {
302 std.heap.c_allocator.destroy(progress);
303}
304
305// ABI warning
306export fn stage2_progress_start_root(
307 progress: *std.Progress,
308 name_ptr: [*]const u8,
309 name_len: usize,
310 estimated_total_items: usize,
311) *std.Progress.Node {
312 return progress.start(name_ptr[0..name_len], estimated_total_items);
313}
314
315// ABI warning
316export fn stage2_progress_disable_tty(progress: *std.Progress) void {
317 progress.terminal = null;
318}
319
320// ABI warning
321export fn stage2_progress_start(
322 node: *std.Progress.Node,
323 name_ptr: [*]const u8,
324 name_len: usize,
325 estimated_total_items: usize,
326) *std.Progress.Node {
327 const child_node = std.heap.c_allocator.create(std.Progress.Node) catch @panic("out of memory");
328 child_node.* = node.start(
329 name_ptr[0..name_len],
330 estimated_total_items,
331 );
332 child_node.activate();
333 return child_node;
334}
335
336// ABI warning
337export fn stage2_progress_end(node: *std.Progress.Node) void {
338 node.end();
339 if (&node.context.root != node) {
340 std.heap.c_allocator.destroy(node);
341 }
342}
343
344// ABI warning
345export fn stage2_progress_complete_one(node: *std.Progress.Node) void {
346 node.completeOne();
347}
348
349// ABI warning
350export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usize, total_count: usize) void {
351 node.setCompletedItems(done_count);
352 node.setEstimatedTotalItems(total_count);
353 node.activate();
354 node.context.maybeRefresh();
355}
356
357// ABI warning
358pub const Stage2Target = extern struct {
359 arch: c_int,
360 os: OS,
361 abi: c_int,
362
363 is_native_os: bool,
364 is_native_cpu: bool,
365
366 llvm_cpu_name: ?[*:0]const u8,
367 llvm_cpu_features: ?[*:0]const u8,
368 llvm_target_abi: ?[*:0]const u8,
369};
370
371// ABI warning
372const Stage2SemVer = extern struct {
373 major: u32,
374 minor: u32,
375 patch: u32,
376};
377
378// ABI warning
379export fn stage2_cimport(
380 stage1: *Module,
381 c_src_ptr: [*]const u8,
382 c_src_len: usize,
383 out_zig_path_ptr: *[*]const u8,
384 out_zig_path_len: *usize,
385 out_errors_ptr: *[*]translate_c.ClangErrMsg,
386 out_errors_len: *usize,
387) Error {
388 const comp = @intToPtr(*Compilation, stage1.userdata);
389 const c_src = c_src_ptr[0..c_src_len];
390 const result = comp.cImport(c_src) catch |err| switch (err) {
391 error.SystemResources => return .SystemResources,
392 error.OperationAborted => return .OperationAborted,
393 error.BrokenPipe => return .BrokenPipe,
394 error.DiskQuota => return .DiskQuota,
395 error.FileTooBig => return .FileTooBig,
396 error.NoSpaceLeft => return .NoSpaceLeft,
397 error.AccessDenied => return .AccessDenied,
398 error.OutOfMemory => return .OutOfMemory,
399 error.Unexpected => return .Unexpected,
400 error.InputOutput => return .FileSystem,
401 error.ASTUnitFailure => return .ASTUnitFailure,
402 error.CacheUnavailable => return .CacheUnavailable,
403 else => return .Unexpected,
404 };
405 out_zig_path_ptr.* = result.out_zig_path.ptr;
406 out_zig_path_len.* = result.out_zig_path.len;
407 out_errors_ptr.* = result.errors.ptr;
408 out_errors_len.* = result.errors.len;
409 if (result.errors.len != 0) return .CCompileErrors;
410 return Error.None;
411}
412
413export fn stage2_add_link_lib(
414 stage1: *Module,
415 lib_name_ptr: [*c]const u8,
416 lib_name_len: usize,
417 symbol_name_ptr: [*c]const u8,
418 symbol_name_len: usize,
419) ?[*:0]const u8 {
420 _ = symbol_name_len;
421 _ = symbol_name_ptr;
422 const comp = @intToPtr(*Compilation, stage1.userdata);
423 const lib_name = lib_name_ptr[0..lib_name_len];
424 const target = comp.getTarget();
425 const is_libc = target_util.is_libc_lib_name(target, lib_name);
426 if (is_libc) {
427 if (!comp.bin_file.options.link_libc and !comp.bin_file.options.parent_compilation_link_libc) {
428 return "dependency on libc must be explicitly specified in the build command";
429 }
430 return null;
431 }
432 if (target_util.is_libcpp_lib_name(target, lib_name)) {
433 if (!comp.bin_file.options.link_libcpp) {
434 return "dependency on libc++ must be explicitly specified in the build command";
435 }
436 return null;
437 }
438 if (!target.isWasm() and !comp.bin_file.options.pic) {
439 return std.fmt.allocPrintZ(
440 comp.gpa,
441 "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.",
442 .{ lib_name, lib_name },
443 ) catch "out of memory";
444 }
445 comp.stage1AddLinkLib(lib_name) catch |err| {
446 return std.fmt.allocPrintZ(comp.gpa, "unable to add link lib '{s}': {s}", .{
447 lib_name, @errorName(err),
448 }) catch "out of memory";
449 };
450 return null;
451}
452
453export fn stage2_fetch_file(
454 stage1: *Module,
455 path_ptr: [*]const u8,
456 path_len: usize,
457 result_len: *usize,
458) ?[*]const u8 {
459 const comp = @intToPtr(*Compilation, stage1.userdata);
460 const file_path = path_ptr[0..path_len];
461 const max_file_size = std.math.maxInt(u32);
462 const contents = if (comp.whole_cache_manifest) |man| blk: {
463 comp.whole_cache_manifest_mutex.lock();
464 defer comp.whole_cache_manifest_mutex.unlock();
465 break :blk man.addFilePostFetch(file_path, max_file_size) catch return null;
466 } else std.fs.cwd().readFileAlloc(comp.gpa, file_path, max_file_size) catch return null;
467 result_len.* = contents.len;
468 // TODO https://github.com/ziglang/zig/issues/3328#issuecomment-716749475
469 if (contents.len == 0) return @intToPtr(?[*]const u8, 0x1);
470 return contents.ptr;
471}
472
473export fn stage2_append_symbol(stage1: *Module, name_ptr: [*c]const u8, name_len: usize) Error {
474 if (name_len == 0) return Error.None;
475 const comp = @intToPtr(*Compilation, stage1.userdata);
476 const sym_name = comp.gpa.dupe(u8, name_ptr[0..name_len]) catch return Error.OutOfMemory;
477 comp.export_symbol_names.append(comp.gpa, sym_name) catch return Error.OutOfMemory;
478 return Error.None;
479}
src/stage1/all_types.hpp deleted-4746
...@@ -1,4746 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_ALL_TYPES_HPP
9#define ZIG_ALL_TYPES_HPP
10
11#include "list.hpp"
12#include "buffer.hpp"
13#include "zig_llvm.h"
14#include "hash_map.hpp"
15#include "errmsg.hpp"
16#include "bigint.hpp"
17#include "bigfloat.hpp"
18#include "target.hpp"
19#include "tokenizer.hpp"
20
21struct AstNode;
22struct ZigFn;
23struct Scope;
24struct ScopeBlock;
25struct ScopeFnDef;
26struct ScopeExpr;
27struct ZigType;
28struct ZigVar;
29struct ErrorTableEntry;
30struct BuiltinFnEntry;
31struct TypeStructField;
32struct CodeGen;
33struct ZigValue;
34struct Stage1ZirInst;
35struct Stage1AirInst;
36struct Stage1AirInstCast;
37struct Stage1AirInstAlloca;
38struct Stage1AirInstCall;
39struct Stage1AirInstAwait;
40struct Stage1ZirBasicBlock;
41struct Stage1AirBasicBlock;
42struct ScopeDecls;
43struct ZigWindowsSDK;
44struct Tld;
45struct TldExport;
46struct IrAnalyze;
47struct ResultLoc;
48struct ResultLocPeer;
49struct ResultLocPeerParent;
50struct ResultLocBitCast;
51struct ResultLocCast;
52struct ResultLocReturn;
53struct Stage1Air;
54
55enum FileExt {
56 FileExtUnknown,
57 FileExtAsm,
58 FileExtC,
59 FileExtCpp,
60 FileExtHeader,
61 FileExtLLVMIr,
62 FileExtLLVMBitCode,
63};
64
65enum PtrLen {
66 PtrLenUnknown,
67 PtrLenSingle,
68 PtrLenC,
69};
70
71enum CallingConvention {
72 CallingConventionUnspecified,
73 CallingConventionC,
74 CallingConventionNaked,
75 CallingConventionAsync,
76 CallingConventionInline,
77 CallingConventionInterrupt,
78 CallingConventionSignal,
79 CallingConventionStdcall,
80 CallingConventionFastcall,
81 CallingConventionVectorcall,
82 CallingConventionThiscall,
83 CallingConventionAPCS,
84 CallingConventionAAPCS,
85 CallingConventionAAPCSVFP,
86 CallingConventionSysV,
87 CallingConventionWin64,
88 CallingConventionPtxKernel,
89 CallingConventionAmdgpuKernel
90};
91
92// Stage 1 supports only the generic address space
93enum AddressSpace {
94 AddressSpaceGeneric,
95 AddressSpaceGS,
96 AddressSpaceFS,
97 AddressSpaceSS,
98 AddressSpaceGlobal,
99 AddressSpaceConstant,
100 AddressSpaceParam,
101 AddressSpaceShared,
102 AddressSpaceLocal,
103};
104
105// This one corresponds to the builtin.zig enum.
106enum BuiltinPtrSize {
107 BuiltinPtrSizeOne,
108 BuiltinPtrSizeMany,
109 BuiltinPtrSizeSlice,
110 BuiltinPtrSizeC,
111};
112
113enum UndefAllowed {
114 UndefOk,
115 UndefBad,
116 LazyOkNoUndef,
117 LazyOk,
118};
119
120enum X64CABIClass {
121 X64CABIClass_Unknown,
122 X64CABIClass_MEMORY,
123 X64CABIClass_MEMORY_nobyval,
124 X64CABIClass_INTEGER,
125 X64CABIClass_SSE,
126 X64CABIClass_AGG,
127};
128
129struct Stage1Zir {
130 ZigList<Stage1ZirBasicBlock *> basic_block_list;
131 Buf *name;
132 ZigFn *name_fn;
133 Scope *begin_scope;
134 ErrorMsg *first_err_trace_msg;
135 ZigList<Tld *> tld_list;
136
137 bool is_inline;
138 bool need_err_code_spill;
139};
140
141struct Stage1Air {
142 ZigList<Stage1AirBasicBlock *> basic_block_list;
143 Buf *name;
144 ZigFn *name_fn;
145 size_t mem_slot_count;
146 size_t next_debug_id;
147 Buf *c_import_buf;
148 AstNode *source_node;
149 Stage1Air *parent_exec;
150 Stage1Zir *source_exec;
151 Scope *begin_scope;
152 ErrorMsg *first_err_trace_msg;
153 ZigList<Tld *> tld_list;
154
155 bool is_inline;
156 bool need_err_code_spill;
157
158 // This is a function for use in the debugger to print
159 // the source location.
160 void src();
161};
162
163enum OutType {
164 OutTypeUnknown,
165 OutTypeExe,
166 OutTypeLib,
167 OutTypeObj,
168};
169
170enum ConstParentId {
171 ConstParentIdNone,
172 ConstParentIdStruct,
173 ConstParentIdErrUnionCode,
174 ConstParentIdErrUnionPayload,
175 ConstParentIdOptionalPayload,
176 ConstParentIdArray,
177 ConstParentIdUnion,
178 ConstParentIdScalar,
179};
180
181struct ConstParent {
182 ConstParentId id;
183
184 union {
185 struct {
186 ZigValue *array_val;
187 size_t elem_index;
188 } p_array;
189 struct {
190 ZigValue *struct_val;
191 size_t field_index;
192 } p_struct;
193 struct {
194 ZigValue *err_union_val;
195 } p_err_union_code;
196 struct {
197 ZigValue *err_union_val;
198 } p_err_union_payload;
199 struct {
200 ZigValue *optional_val;
201 } p_optional_payload;
202 struct {
203 ZigValue *union_val;
204 } p_union;
205 struct {
206 ZigValue *scalar_val;
207 } p_scalar;
208 } data;
209};
210
211struct ConstStructValue {
212 ZigValue **fields;
213};
214
215struct ConstUnionValue {
216 BigInt tag;
217 ZigValue *payload;
218};
219
220enum ConstArraySpecial {
221 ConstArraySpecialNone,
222 ConstArraySpecialUndef,
223 ConstArraySpecialBuf,
224};
225
226struct ConstArrayValue {
227 ConstArraySpecial special;
228 union {
229 struct {
230 ZigValue *elements;
231 } s_none;
232 Buf *s_buf;
233 } data;
234};
235
236enum ConstPtrSpecial {
237 // Enforce explicitly setting this ID by making the zero value invalid.
238 ConstPtrSpecialInvalid,
239 // The pointer is a reference to a single object.
240 ConstPtrSpecialRef,
241 // The pointer points to an element in an underlying array.
242 // Not to be confused with ConstPtrSpecialSubArray.
243 ConstPtrSpecialBaseArray,
244 // The pointer points to a field in an underlying struct.
245 ConstPtrSpecialBaseStruct,
246 // The pointer points to the error set field of an error union
247 ConstPtrSpecialBaseErrorUnionCode,
248 // The pointer points to the payload field of an error union
249 ConstPtrSpecialBaseErrorUnionPayload,
250 // The pointer points to the payload field of an optional
251 ConstPtrSpecialBaseOptionalPayload,
252 // This means that we did a compile-time pointer reinterpret and we cannot
253 // understand the value of pointee at compile time. However, we will still
254 // emit a binary with a compile time known address.
255 // In this case index is the numeric address value.
256 ConstPtrSpecialHardCodedAddr,
257 // This means that the pointer represents memory of assigning to _.
258 // That is, storing discards the data, and loading is invalid.
259 ConstPtrSpecialDiscard,
260 // This is actually a function.
261 ConstPtrSpecialFunction,
262 // This means the pointer is null. This is only allowed when the type is ?*T.
263 // We use this instead of ConstPtrSpecialHardCodedAddr because often we check
264 // for that value to avoid doing comptime work.
265 // We need the data layout for ConstCastOnly == true
266 // types to be the same, so all optionals of pointer types use x_ptr
267 // instead of x_optional.
268 ConstPtrSpecialNull,
269 // The pointer points to a sub-array (not an individual element).
270 // Not to be confused with ConstPtrSpecialBaseArray. However, it uses the same
271 // union payload struct (base_array).
272 ConstPtrSpecialSubArray,
273};
274
275enum ConstPtrMut {
276 // The pointer points to memory that is known at compile time and immutable.
277 ConstPtrMutComptimeConst,
278 // This means that the pointer points to memory used by a comptime variable,
279 // so attempting to write a non-compile-time known value is an error
280 // But the underlying value is allowed to change at compile time.
281 ConstPtrMutComptimeVar,
282 // The pointer points to memory that is known only at runtime.
283 // For example it may point to the initializer value of a variable.
284 ConstPtrMutRuntimeVar,
285 // The pointer points to memory for which it must be inferred whether the
286 // value is comptime known or not.
287 ConstPtrMutInfer,
288};
289
290struct ConstPtrValue {
291 ConstPtrSpecial special;
292 ConstPtrMut mut;
293
294 union {
295 struct {
296 ZigValue *pointee;
297 } ref;
298 struct {
299 ZigValue *array_val;
300 size_t elem_index;
301 } base_array;
302 struct {
303 ZigValue *struct_val;
304 size_t field_index;
305 } base_struct;
306 struct {
307 ZigValue *err_union_val;
308 } base_err_union_code;
309 struct {
310 ZigValue *err_union_val;
311 } base_err_union_payload;
312 struct {
313 ZigValue *optional_val;
314 } base_optional_payload;
315 struct {
316 uint64_t addr;
317 } hard_coded_addr;
318 struct {
319 ZigFn *fn_entry;
320 } fn;
321 } data;
322};
323
324struct ConstErrValue {
325 ZigValue *error_set;
326 ZigValue *payload;
327};
328
329struct ConstBoundFnValue {
330 ZigFn *fn;
331 Stage1AirInst *first_arg;
332 AstNode *first_arg_src;
333};
334
335struct ConstArgTuple {
336 size_t start_index;
337 size_t end_index;
338};
339
340enum ConstValSpecial {
341 // The value is only available at runtime. However there may be runtime hints
342 // narrowing the possible values down via the `data.rh_*` fields.
343 ConstValSpecialRuntime,
344 // The value is comptime-known and resolved. The `data.x_*` fields can be
345 // accessed.
346 ConstValSpecialStatic,
347 // The value is comptime-known to be `undefined`.
348 ConstValSpecialUndef,
349 // The value is comptime-known, but not yet resolved. The lazy value system
350 // helps avoid dependency loops by providing answers to certain questions
351 // about values without forcing them to be resolved. For example, the
352 // equation `@sizeOf(Foo) == 0` can be resolved without forcing the struct
353 // layout of `Foo` because we can know whether `Foo` is zero bits without
354 // performing field layout.
355 // A `ZigValue` can be converted from Lazy to Static/Undef by calling the
356 // appropriate resolve function.
357 ConstValSpecialLazy,
358};
359
360enum RuntimeHintErrorUnion {
361 RuntimeHintErrorUnionUnknown,
362 RuntimeHintErrorUnionError,
363 RuntimeHintErrorUnionNonError,
364};
365
366enum RuntimeHintOptional {
367 RuntimeHintOptionalUnknown,
368 RuntimeHintOptionalNull, // TODO is this value even possible? if this is the case it might mean the const value is compile time known.
369 RuntimeHintOptionalNonNull,
370};
371
372enum RuntimeHintPtr {
373 RuntimeHintPtrUnknown,
374 RuntimeHintPtrStack,
375 RuntimeHintPtrNonStack,
376};
377
378enum RuntimeHintSliceId {
379 RuntimeHintSliceIdUnknown,
380 RuntimeHintSliceIdLen,
381};
382
383struct RuntimeHintSlice {
384 enum RuntimeHintSliceId id;
385 uint64_t len;
386};
387
388enum LazyValueId {
389 LazyValueIdInvalid,
390 LazyValueIdAlignOf,
391 LazyValueIdSizeOf,
392 LazyValueIdPtrType,
393 LazyValueIdPtrTypeSimple,
394 LazyValueIdPtrTypeSimpleConst,
395 LazyValueIdOptType,
396 LazyValueIdSliceType,
397 LazyValueIdFnType,
398 LazyValueIdErrUnionType,
399 LazyValueIdArrayType,
400 LazyValueIdTypeInfoDecls,
401};
402
403struct LazyValue {
404 LazyValueId id;
405};
406
407struct LazyValueTypeInfoDecls {
408 LazyValue base;
409
410 IrAnalyze *ira;
411
412 ScopeDecls *decls_scope;
413 AstNode *source_node;
414};
415
416struct LazyValueAlignOf {
417 LazyValue base;
418
419 IrAnalyze *ira;
420 Stage1AirInst *target_type;
421};
422
423struct LazyValueSizeOf {
424 LazyValue base;
425
426 IrAnalyze *ira;
427 Stage1AirInst *target_type;
428
429 bool bit_size;
430};
431
432struct LazyValueSliceType {
433 LazyValue base;
434
435 IrAnalyze *ira;
436 Stage1AirInst *sentinel; // can be null
437 Stage1AirInst *elem_type;
438 Stage1AirInst *align_inst; // can be null
439
440 bool is_const;
441 bool is_volatile;
442 bool is_allowzero;
443};
444
445struct LazyValueArrayType {
446 LazyValue base;
447
448 IrAnalyze *ira;
449 Stage1AirInst *sentinel; // can be null
450 Stage1AirInst *elem_type;
451 uint64_t length;
452};
453
454struct LazyValuePtrType {
455 LazyValue base;
456
457 IrAnalyze *ira;
458 Stage1AirInst *sentinel; // can be null
459 Stage1AirInst *elem_type;
460 Stage1AirInst *align_inst; // can be null
461
462 PtrLen ptr_len;
463 uint32_t bit_offset_in_host;
464
465 uint32_t host_int_bytes;
466 bool is_const;
467 bool is_volatile;
468 bool is_allowzero;
469};
470
471struct LazyValuePtrTypeSimple {
472 LazyValue base;
473
474 IrAnalyze *ira;
475 Stage1AirInst *elem_type;
476};
477
478struct LazyValueOptType {
479 LazyValue base;
480
481 IrAnalyze *ira;
482 Stage1AirInst *payload_type;
483};
484
485struct LazyValueFnType {
486 LazyValue base;
487
488 IrAnalyze *ira;
489 AstNode *proto_node;
490 Stage1AirInst **param_types;
491 Stage1AirInst *align_inst; // can be null
492 Stage1AirInst *return_type;
493
494 CallingConvention cc;
495 bool is_generic;
496};
497
498struct LazyValueErrUnionType {
499 LazyValue base;
500
501 IrAnalyze *ira;
502 Stage1AirInst *err_set_type;
503 Stage1AirInst *payload_type;
504 Buf *type_name;
505};
506
507struct ZigValue {
508 ZigType *type;
509 // This field determines how the value is stored. It must be checked
510 // before accessing the `data` union.
511 ConstValSpecial special;
512 uint32_t llvm_align;
513 ConstParent parent;
514 LLVMValueRef llvm_value;
515 LLVMValueRef llvm_global;
516
517 union {
518 // populated if special == ConstValSpecialLazy
519 LazyValue *x_lazy;
520
521 // populated if special == ConstValSpecialStatic
522 BigInt x_bigint;
523 BigFloat x_bigfloat;
524 float16_t x_f16;
525 float x_f32;
526 double x_f64;
527 extFloat80_t x_f80;
528 float128_t x_f128;
529 bool x_bool;
530 ConstBoundFnValue x_bound_fn;
531 ZigType *x_type;
532 ZigValue *x_optional;
533 ConstErrValue x_err_union;
534 ErrorTableEntry *x_err_set;
535 BigInt x_enum_tag;
536 ConstStructValue x_struct;
537 ConstUnionValue x_union;
538 ConstArrayValue x_array;
539 ConstPtrValue x_ptr;
540 ConstArgTuple x_arg_tuple;
541 Buf *x_enum_literal;
542
543 // populated if special == ConstValSpecialRuntime
544 RuntimeHintErrorUnion rh_error_union;
545 RuntimeHintOptional rh_maybe;
546 RuntimeHintPtr rh_ptr;
547 RuntimeHintSlice rh_slice;
548 } data;
549
550 // uncomment this to find bugs. can't leave it uncommented because of a gcc-9 warning
551 //ZigValue& operator= (const ZigValue &other) = delete; // use copy_const_val
552
553 ZigValue(const ZigValue &other) = delete; // plz zero initialize with ZigValue val = {};
554
555 // for use in debuggers
556 void dump();
557};
558
559enum ReturnKnowledge {
560 ReturnKnowledgeUnknown,
561 ReturnKnowledgeKnownError,
562 ReturnKnowledgeKnownNonError,
563 ReturnKnowledgeKnownNull,
564 ReturnKnowledgeKnownNonNull,
565 ReturnKnowledgeSkipDefers,
566};
567
568enum VisibMod {
569 VisibModPrivate,
570 VisibModPub,
571};
572
573enum GlobalLinkageId {
574 GlobalLinkageIdInternal,
575 GlobalLinkageIdStrong,
576 GlobalLinkageIdWeak,
577 GlobalLinkageIdLinkOnce,
578};
579
580enum TldId {
581 TldIdVar,
582 TldIdFn,
583 TldIdContainer,
584 TldIdCompTime,
585 TldIdUsingNamespace,
586};
587
588enum TldResolution {
589 TldResolutionUnresolved,
590 TldResolutionResolving,
591 TldResolutionInvalid,
592 TldResolutionOkLazy,
593 TldResolutionOk,
594};
595
596struct Tld {
597 TldId id;
598 Buf *name;
599 VisibMod visib_mod;
600 AstNode *source_node;
601
602 ZigType *import;
603 Scope *parent_scope;
604 TldResolution resolution;
605};
606
607struct TldVar {
608 Tld base;
609
610 ZigVar *var;
611 Buf *extern_lib_name;
612 bool analyzing_type; // flag to detect dependency loops
613};
614
615struct TldFn {
616 Tld base;
617
618 ZigFn *fn_entry;
619 Buf *extern_lib_name;
620};
621
622struct TldContainer {
623 Tld base;
624
625 ScopeDecls *decls_scope;
626 ZigType *type_entry;
627};
628
629struct TldCompTime {
630 Tld base;
631};
632
633struct TldUsingNamespace {
634 Tld base;
635
636 ZigValue *using_namespace_value;
637};
638
639struct TypeEnumField {
640 Buf *name;
641 BigInt value;
642 uint32_t decl_index;
643 AstNode *decl_node;
644};
645
646struct TypeUnionField {
647 Buf *name;
648 ZigType *type_entry; // available after ResolveStatusSizeKnown
649 ZigValue *type_val; // available after ResolveStatusZeroBitsKnown
650 TypeEnumField *enum_field;
651 AstNode *decl_node;
652 uint32_t gen_index;
653 uint32_t align;
654};
655
656enum NodeType {
657 NodeTypeFnProto,
658 NodeTypeFnDef,
659 NodeTypeParamDecl,
660 NodeTypeBlock,
661 NodeTypeGroupedExpr,
662 NodeTypeReturnExpr,
663 NodeTypeDefer,
664 NodeTypeVariableDeclaration,
665 NodeTypeTestDecl,
666 NodeTypeBinOpExpr,
667 NodeTypeCatchExpr,
668 NodeTypeFloatLiteral,
669 NodeTypeIntLiteral,
670 NodeTypeStringLiteral,
671 NodeTypeCharLiteral,
672 NodeTypeIdentifier,
673 NodeTypePrefixOpExpr,
674 NodeTypePointerType,
675 NodeTypeFnCallExpr,
676 NodeTypeArrayAccessExpr,
677 NodeTypeSliceExpr,
678 NodeTypeFieldAccessExpr,
679 NodeTypePtrDeref,
680 NodeTypeUnwrapOptional,
681 NodeTypeUsingNamespace,
682 NodeTypeUnreachable,
683 NodeTypeIfBoolExpr,
684 NodeTypeWhileExpr,
685 NodeTypeForExpr,
686 NodeTypeSwitchExpr,
687 NodeTypeSwitchProng,
688 NodeTypeSwitchRange,
689 NodeTypeCompTime,
690 NodeTypeNoSuspend,
691 NodeTypeBreak,
692 NodeTypeContinue,
693 NodeTypeAsmExpr,
694 NodeTypeContainerDecl,
695 NodeTypeStructField,
696 NodeTypeContainerInitExpr,
697 NodeTypeStructValueField,
698 NodeTypeArrayType,
699 NodeTypeInferredArrayType,
700 NodeTypeErrorType,
701 NodeTypeIfErrorExpr,
702 NodeTypeIfOptional,
703 NodeTypeErrorSetDecl,
704 NodeTypeErrorSetField,
705 NodeTypeResume,
706 NodeTypeAwaitExpr,
707 NodeTypeSuspend,
708 NodeTypeAnyFrameType,
709 // main_token points to the identifier.
710 NodeTypeEnumLiteral,
711 NodeTypeAnyTypeField,
712};
713
714enum FnInline {
715 FnInlineAuto,
716 FnInlineAlways,
717 FnInlineNever,
718};
719
720struct AstNodeFnProto {
721 Buf *name;
722 ZigList<AstNode *> params;
723 AstNode *return_type;
724 AstNode *fn_def_node;
725 // populated if this is an extern declaration
726 Buf *lib_name;
727 // populated if the "align A" is present
728 AstNode *align_expr;
729 // populated if the "section(S)" is present
730 AstNode *section_expr;
731 // populated if the "callconv(S)" is present
732 AstNode *callconv_expr;
733
734 TokenIndex doc_comments;
735
736 // This is set based only on the existence of a noinline or inline keyword.
737 // This is then resolved to an is_noinline bool and (potentially .Inline)
738 // calling convention in resolve_decl_fn() in analyze.cpp.
739 FnInline fn_inline;
740
741 VisibMod visib_mod;
742 bool auto_err_set;
743 bool is_var_args;
744 bool is_extern;
745 bool is_export;
746};
747
748struct AstNodeFnDef {
749 AstNode *fn_proto;
750 AstNode *body;
751};
752
753struct AstNodeParamDecl {
754 Buf *name;
755 AstNode *type;
756 TokenIndex doc_comments;
757 TokenIndex anytype_token;
758 bool is_noalias;
759 bool is_comptime;
760 bool is_var_args;
761};
762
763struct AstNodeBlock {
764 Buf *name;
765 ZigList<AstNode *> statements;
766};
767
768enum ReturnKind {
769 ReturnKindUnconditional,
770 ReturnKindError,
771};
772
773struct AstNodeReturnExpr {
774 ReturnKind kind;
775 // might be null in case of return void;
776 AstNode *expr;
777};
778
779struct AstNodeDefer {
780 ReturnKind kind;
781 AstNode *err_payload;
782 AstNode *expr;
783
784 // temporary data used in IR generation
785 Scope *child_scope;
786 Scope *expr_scope;
787};
788
789struct AstNodeVariableDeclaration {
790 Buf *symbol;
791 // one or both of type and expr will be non null
792 AstNode *type;
793 AstNode *expr;
794 // populated if this is an extern declaration
795 Buf *lib_name;
796 // populated if the "align(A)" is present
797 AstNode *align_expr;
798 // populated if the "section(S)" is present
799 AstNode *section_expr;
800 TokenIndex doc_comments;
801
802 TokenIndex threadlocal_tok;
803 VisibMod visib_mod;
804 bool is_const;
805 bool is_comptime;
806 bool is_export;
807 bool is_extern;
808};
809
810struct AstNodeTestDecl {
811 // nullptr if the test declaration has no name
812 Buf *name;
813
814 AstNode *body;
815};
816
817enum BinOpType {
818 BinOpTypeInvalid,
819 BinOpTypeAssign,
820 BinOpTypeAssignTimes,
821 BinOpTypeAssignTimesSat,
822 BinOpTypeAssignTimesWrap,
823 BinOpTypeAssignDiv,
824 BinOpTypeAssignMod,
825 BinOpTypeAssignPlus,
826 BinOpTypeAssignPlusSat,
827 BinOpTypeAssignPlusWrap,
828 BinOpTypeAssignMinus,
829 BinOpTypeAssignMinusSat,
830 BinOpTypeAssignMinusWrap,
831 BinOpTypeAssignBitShiftLeft,
832 BinOpTypeAssignBitShiftLeftSat,
833 BinOpTypeAssignBitShiftRight,
834 BinOpTypeAssignBitAnd,
835 BinOpTypeAssignBitXor,
836 BinOpTypeAssignBitOr,
837 BinOpTypeBoolOr,
838 BinOpTypeBoolAnd,
839 BinOpTypeCmpEq,
840 BinOpTypeCmpNotEq,
841 BinOpTypeCmpLessThan,
842 BinOpTypeCmpGreaterThan,
843 BinOpTypeCmpLessOrEq,
844 BinOpTypeCmpGreaterOrEq,
845 BinOpTypeBinOr,
846 BinOpTypeBinXor,
847 BinOpTypeBinAnd,
848 BinOpTypeBitShiftLeft,
849 BinOpTypeBitShiftLeftSat,
850 BinOpTypeBitShiftRight,
851 BinOpTypeAdd,
852 BinOpTypeAddSat,
853 BinOpTypeAddWrap,
854 BinOpTypeSub,
855 BinOpTypeSubSat,
856 BinOpTypeSubWrap,
857 BinOpTypeMult,
858 BinOpTypeMultSat,
859 BinOpTypeMultWrap,
860 BinOpTypeDiv,
861 BinOpTypeMod,
862 BinOpTypeUnwrapOptional,
863 BinOpTypeArrayCat,
864 BinOpTypeArrayMult,
865 BinOpTypeErrorUnion,
866 BinOpTypeMergeErrorSets,
867};
868
869struct AstNodeBinOpExpr {
870 AstNode *op1;
871 BinOpType bin_op;
872 AstNode *op2;
873};
874
875struct AstNodeCatchExpr {
876 AstNode *op1;
877 AstNode *symbol; // can be null
878 AstNode *op2;
879};
880
881struct AstNodeUnwrapOptional {
882 AstNode *expr;
883};
884
885// Must be synchronized with std.builtin.CallOptions.Modifier
886enum CallModifier {
887 CallModifierNone,
888 CallModifierAsync,
889 CallModifierNeverTail,
890 CallModifierNeverInline,
891 CallModifierNoSuspend,
892 CallModifierAlwaysTail,
893 CallModifierAlwaysInline,
894 CallModifierCompileTime,
895
896 // These are additional tags in the compiler, but not exposed in the std lib.
897 CallModifierBuiltin,
898};
899
900struct AstNodeFnCallExpr {
901 AstNode *fn_ref_expr;
902 ZigList<AstNode *> params;
903 CallModifier modifier;
904 bool seen; // used by @compileLog
905};
906
907// Must be kept in sync with std.builtin.PrefetchOptions.Rw
908enum PrefetchRw {
909 PrefetchRwRead,
910 PrefetchRwWrite,
911};
912
913// Must be kept in sync with std.builtin.PrefetchOptions.Cache
914enum PrefetchCache {
915 PrefetchCacheInstruction,
916 PrefetchCacheData,
917};
918
919struct AstNodeArrayAccessExpr {
920 AstNode *array_ref_expr;
921 AstNode *subscript;
922};
923
924struct AstNodeSliceExpr {
925 AstNode *array_ref_expr;
926 AstNode *start;
927 AstNode *end;
928 AstNode *sentinel; // can be null
929};
930
931struct AstNodeFieldAccessExpr {
932 AstNode *struct_expr;
933 Buf *field_name;
934};
935
936struct AstNodePtrDerefExpr {
937 AstNode *target;
938};
939
940enum PrefixOp {
941 PrefixOpInvalid,
942 PrefixOpBoolNot,
943 PrefixOpBinNot,
944 PrefixOpNegation,
945 PrefixOpNegationWrap,
946 PrefixOpOptional,
947 PrefixOpAddrOf,
948};
949
950struct AstNodePrefixOpExpr {
951 PrefixOp prefix_op;
952 AstNode *primary_expr;
953};
954
955struct AstNodePointerType {
956 TokenIndex star_token;
957 TokenIndex allow_zero_token;
958 TokenIndex bit_offset_start;
959 TokenIndex host_int_bytes;
960
961 AstNode *sentinel;
962 AstNode *align_expr;
963 AstNode *op_expr;
964 bool is_const;
965 bool is_volatile;
966};
967
968struct AstNodeInferredArrayType {
969 AstNode *sentinel; // can be null
970 AstNode *child_type;
971};
972
973struct AstNodeArrayType {
974 AstNode *size;
975 AstNode *sentinel;
976 AstNode *child_type;
977 AstNode *align_expr;
978 TokenIndex allow_zero_token;
979 bool is_const;
980 bool is_volatile;
981};
982
983struct AstNodeUsingNamespace {
984 VisibMod visib_mod;
985 AstNode *expr;
986};
987
988struct AstNodeIfBoolExpr {
989 AstNode *condition;
990 AstNode *then_block;
991 AstNode *else_node; // null, block node, or other if expr node
992};
993
994struct AstNodeTryExpr {
995 Buf *var_symbol;
996 AstNode *target_node;
997 AstNode *then_node;
998 AstNode *else_node;
999 Buf *err_symbol;
1000 bool var_is_ptr;
1001};
1002
1003struct AstNodeTestExpr {
1004 Buf *var_symbol;
1005 bool var_is_ptr;
1006 AstNode *target_node;
1007 AstNode *then_node;
1008 AstNode *else_node; // null, block node, or other if expr node
1009};
1010
1011struct AstNodeWhileExpr {
1012 Buf *name;
1013 AstNode *condition;
1014 Buf *var_symbol;
1015 AstNode *continue_expr;
1016 AstNode *body;
1017 AstNode *else_node;
1018 Buf *err_symbol;
1019 bool is_inline;
1020 bool var_is_ptr;
1021};
1022
1023struct AstNodeForExpr {
1024 Buf *name;
1025 AstNode *array_expr;
1026 AstNode *elem_node; // always a symbol
1027 AstNode *index_node; // always a symbol, might be null
1028 AstNode *body;
1029 AstNode *else_node; // can be null
1030 bool elem_is_ptr;
1031 bool is_inline;
1032};
1033
1034struct AstNodeSwitchExpr {
1035 AstNode *expr;
1036 ZigList<AstNode *> prongs;
1037};
1038
1039struct AstNodeSwitchProng {
1040 ZigList<AstNode *> items;
1041 AstNode *var_symbol;
1042 AstNode *expr;
1043 bool var_is_ptr;
1044 bool any_items_are_range;
1045 bool is_inline;
1046};
1047
1048struct AstNodeSwitchRange {
1049 AstNode *start;
1050 AstNode *end;
1051};
1052
1053struct AstNodeCompTime {
1054 AstNode *expr;
1055};
1056
1057struct AstNodeNoSuspend {
1058 AstNode *expr;
1059};
1060
1061struct AsmOutput {
1062 Buf *asm_symbolic_name;
1063 Buf *constraint;
1064 Buf *variable_name;
1065 AstNode *return_type; // null unless "=r" and return
1066};
1067
1068struct AsmInput {
1069 Buf *asm_symbolic_name;
1070 Buf *constraint;
1071 AstNode *expr;
1072};
1073
1074struct SrcPos {
1075 size_t line;
1076 size_t column;
1077};
1078
1079enum AsmTokenId {
1080 AsmTokenIdTemplate,
1081 AsmTokenIdPercent,
1082 AsmTokenIdVar,
1083 AsmTokenIdUniqueId,
1084};
1085
1086struct AsmToken {
1087 enum AsmTokenId id;
1088 size_t start;
1089 size_t end;
1090};
1091
1092struct AstNodeAsmExpr {
1093 TokenIndex volatile_token;
1094 AstNode *asm_template;
1095 ZigList<AsmOutput*> output_list;
1096 ZigList<AsmInput*> input_list;
1097 ZigList<Buf*> clobber_list;
1098};
1099
1100enum ContainerKind {
1101 ContainerKindStruct,
1102 ContainerKindEnum,
1103 ContainerKindUnion,
1104 ContainerKindOpaque,
1105};
1106
1107enum ContainerLayout {
1108 ContainerLayoutAuto,
1109 ContainerLayoutExtern,
1110 ContainerLayoutPacked,
1111};
1112
1113struct AstNodeContainerDecl {
1114 AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T))
1115 ZigList<AstNode *> fields;
1116 ZigList<AstNode *> decls;
1117 TokenIndex doc_comments;
1118
1119 ContainerKind kind;
1120 ContainerLayout layout;
1121
1122 bool auto_enum, is_root; // union(enum)
1123 bool unsupported_explicit_backing_int;
1124};
1125
1126struct AstNodeErrorSetField {
1127 TokenIndex doc_comments;
1128 AstNode *field_name;
1129};
1130
1131struct AstNodeErrorSetDecl {
1132 // Each AstNode could be AstNodeErrorSetField or just AstNodeSymbolExpr to save memory
1133 ZigList<AstNode *> decls;
1134};
1135
1136struct AstNodeStructField {
1137 Buf *name;
1138 AstNode *type;
1139 AstNode *value;
1140 // populated if the "align(A)" is present
1141 AstNode *align_expr;
1142 TokenIndex doc_comments;
1143 TokenIndex comptime_token;
1144};
1145
1146struct AstNodeStructValueField {
1147 Buf *name;
1148 AstNode *expr;
1149};
1150
1151enum ContainerInitKind {
1152 ContainerInitKindStruct,
1153 ContainerInitKindArray,
1154};
1155
1156struct AstNodeContainerInitExpr {
1157 AstNode *type;
1158 ZigList<AstNode *> entries;
1159 ContainerInitKind kind;
1160};
1161
1162struct AstNodeIdentifier {
1163 Buf *name;
1164 bool is_at_syntax;
1165};
1166
1167struct AstNodeEnumLiteral {
1168 Buf *name;
1169};
1170
1171struct AstNodeBreakExpr {
1172 Buf *name;
1173 AstNode *expr; // may be null
1174};
1175
1176struct AstNodeResumeExpr {
1177 AstNode *expr;
1178};
1179
1180struct AstNodeContinueExpr {
1181 Buf *name;
1182};
1183
1184struct AstNodeAwaitExpr {
1185 AstNode *expr;
1186};
1187
1188struct AstNodeSuspend {
1189 AstNode *block;
1190};
1191
1192struct AstNodeAnyFrameType {
1193 AstNode *payload_type; // can be NULL
1194};
1195
1196struct AstNode {
1197 enum NodeType type;
1198 TokenIndex main_token;
1199 ZigType *owner;
1200 union {
1201 AstNodeFnDef fn_def;
1202 AstNodeFnProto fn_proto;
1203 AstNodeParamDecl param_decl;
1204 AstNodeBlock block;
1205 AstNode * grouped_expr;
1206 AstNodeReturnExpr return_expr;
1207 AstNodeDefer defer;
1208 AstNodeVariableDeclaration variable_declaration;
1209 AstNodeTestDecl test_decl;
1210 AstNodeBinOpExpr bin_op_expr;
1211 AstNodeCatchExpr unwrap_err_expr;
1212 AstNodeUnwrapOptional unwrap_optional;
1213 AstNodePrefixOpExpr prefix_op_expr;
1214 AstNodePointerType pointer_type;
1215 AstNodeFnCallExpr fn_call_expr;
1216 AstNodeArrayAccessExpr array_access_expr;
1217 AstNodeSliceExpr slice_expr;
1218 AstNodeUsingNamespace using_namespace;
1219 AstNodeIfBoolExpr if_bool_expr;
1220 AstNodeTryExpr if_err_expr;
1221 AstNodeTestExpr test_expr;
1222 AstNodeWhileExpr while_expr;
1223 AstNodeForExpr for_expr;
1224 AstNodeSwitchExpr switch_expr;
1225 AstNodeSwitchProng switch_prong;
1226 AstNodeSwitchRange switch_range;
1227 AstNodeCompTime comptime_expr;
1228 AstNodeNoSuspend nosuspend_expr;
1229 AstNodeAsmExpr asm_expr;
1230 AstNodeFieldAccessExpr field_access_expr;
1231 AstNodePtrDerefExpr ptr_deref_expr;
1232 AstNodeContainerDecl container_decl;
1233 AstNodeStructField struct_field;
1234 AstNodeContainerInitExpr container_init_expr;
1235 AstNodeStructValueField struct_val_field;
1236 AstNodeBreakExpr break_expr;
1237 AstNodeContinueExpr continue_expr;
1238 AstNodeArrayType array_type;
1239 AstNodeInferredArrayType inferred_array_type;
1240 AstNodeErrorSetDecl err_set_decl;
1241 AstNodeErrorSetField err_set_field;
1242 AstNodeResumeExpr resume_expr;
1243 AstNodeAwaitExpr await_expr;
1244 AstNodeSuspend suspend;
1245 AstNodeAnyFrameType anyframe_type;
1246
1247 // These are part of an astgen workaround to use less memory by
1248 // memoizing into the AST. Once astgen is modified to only run once
1249 // per corresponding source, this workaround can be removed.
1250 AstNodeIdentifier identifier;
1251 AstNodeEnumLiteral enum_literal;
1252 } data;
1253
1254 // This is a function for use in the debugger to print
1255 // the source location.
1256 void src();
1257};
1258
1259// this struct is allocated with allocate_nonzero
1260struct FnTypeParamInfo {
1261 bool is_noalias;
1262 ZigType *type;
1263};
1264
1265struct GenericFnTypeId {
1266 CodeGen *codegen;
1267 ZigFn *fn_entry;
1268 ZigValue *params;
1269 size_t param_count;
1270};
1271
1272uint32_t generic_fn_type_id_hash(GenericFnTypeId *id);
1273bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b);
1274
1275struct FnTypeId {
1276 ZigType *return_type;
1277 FnTypeParamInfo *param_info;
1278 size_t param_count;
1279 size_t next_param_index;
1280 bool is_var_args;
1281 CallingConvention cc;
1282 uint32_t alignment;
1283};
1284
1285uint32_t fn_type_id_hash(FnTypeId*);
1286bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
1287
1288static const uint32_t VECTOR_INDEX_NONE = UINT32_MAX;
1289static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1;
1290
1291struct InferredStructField {
1292 ZigType *inferred_struct_type;
1293 Buf *field_name;
1294 bool already_resolved;
1295};
1296
1297struct ZigTypePointer {
1298 ZigType *child_type;
1299 ZigType *slice_parent;
1300
1301 // Anonymous struct literal syntax uses this when the result location has
1302 // no type in it. This field is null if this pointer does not refer to
1303 // a field of a currently-being-inferred struct type.
1304 // When this is non-null, the pointer is pointing to the base of the inferred
1305 // struct.
1306 InferredStructField *inferred_struct_field;
1307
1308 // This can be null. If it is non-null, it means the pointer is terminated by this
1309 // sentinel value. This is most commonly used for C-style strings, with a 0 byte
1310 // to specify the length of the memory pointed to.
1311 ZigValue *sentinel;
1312
1313 PtrLen ptr_len;
1314 uint32_t explicit_alignment; // 0 means use ABI alignment
1315
1316 uint32_t bit_offset_in_host;
1317 // size of host integer. 0 means no host integer; this field is aligned
1318 // when vector_index != VECTOR_INDEX_NONE this is the len of the containing vector
1319 uint32_t host_int_bytes;
1320
1321 uint32_t vector_index; // see the VECTOR_INDEX_* constants
1322 bool is_const;
1323 bool is_volatile;
1324 bool allow_zero;
1325 bool resolve_loop_flag_zero_bits;
1326};
1327
1328struct ZigTypeInt {
1329 uint32_t bit_count;
1330 bool is_signed;
1331};
1332
1333struct ZigTypeFloat {
1334 size_t bit_count;
1335};
1336
1337// Needs to have the same memory layout as ZigTypeVector
1338struct ZigTypeArray {
1339 ZigType *child_type;
1340 uint64_t len;
1341 ZigValue *sentinel;
1342};
1343
1344struct TypeStructField {
1345 Buf *name;
1346 ZigType *type_entry; // available after ResolveStatusSizeKnown
1347 ZigValue *type_val; // available after ResolveStatusZeroBitsKnown
1348 size_t src_index;
1349 size_t gen_index;
1350 size_t offset; // byte offset from beginning of struct
1351 AstNode *decl_node;
1352 ZigValue *init_val; // null and then memoized
1353 uint32_t bit_offset_in_host; // offset from the memory at gen_index
1354 uint32_t host_int_bytes; // size of host integer
1355 uint32_t align;
1356 bool is_comptime;
1357};
1358
1359enum ResolveStatus {
1360 ResolveStatusUnstarted,
1361 ResolveStatusInvalid,
1362 ResolveStatusBeingInferred,
1363 ResolveStatusZeroBitsKnown,
1364 ResolveStatusAlignmentKnown,
1365 ResolveStatusSizeKnown,
1366 ResolveStatusLLVMFwdDecl,
1367 ResolveStatusLLVMFull,
1368};
1369
1370struct ZigPackage {
1371 Buf root_src_dir;
1372 Buf root_src_path; // relative to root_src_dir
1373 Buf pkg_path; // a.b.c.d which follows the package dependency chain from the root package
1374
1375 // reminder: hash tables must be initialized before use
1376 HashMap<Buf *, ZigPackage *, buf_hash, buf_eql_buf> package_table;
1377
1378 bool added_to_cache;
1379};
1380
1381// Stuff that only applies to a struct which is the implicit root struct of a file
1382struct RootStruct {
1383 ZigPackage *package;
1384 Buf *path; // relative to root_package->root_src_dir
1385 Buf *source_code;
1386 ZigLLVMDIFile *di_file;
1387 size_t token_count;
1388 TokenId *token_ids;
1389 TokenLoc *token_locs;
1390};
1391
1392enum StructSpecial {
1393 StructSpecialNone,
1394 StructSpecialSlice,
1395 StructSpecialInferredTuple,
1396 StructSpecialInferredStruct,
1397};
1398
1399struct ZigTypeStruct {
1400 AstNode *decl_node;
1401 TypeStructField **fields;
1402 TypeStructField *misaligned_field;
1403 ScopeDecls *decls_scope;
1404 HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
1405 RootStruct *root_struct;
1406 uint32_t *host_int_bytes; // available for packed structs, indexed by gen_index
1407 size_t llvm_full_type_queue_index;
1408
1409 uint32_t src_field_count;
1410 uint32_t gen_field_count;
1411
1412 ContainerLayout layout;
1413 ResolveStatus resolve_status;
1414
1415 StructSpecial special;
1416 // whether any of the fields require comptime
1417 // known after ResolveStatusZeroBitsKnown
1418 bool requires_comptime;
1419 bool resolve_loop_flag_zero_bits;
1420 bool resolve_loop_flag_other;
1421 bool created_by_at_type;
1422};
1423
1424struct ZigTypeOptional {
1425 ZigType *child_type;
1426 ResolveStatus resolve_status;
1427};
1428
1429struct ZigTypeErrorUnion {
1430 ZigType *err_set_type;
1431 ZigType *payload_type;
1432 size_t pad_bytes;
1433 LLVMTypeRef pad_llvm_type;
1434};
1435
1436struct ZigTypeErrorSet {
1437 ErrorTableEntry **errors;
1438 ZigFn *infer_fn;
1439 uint32_t err_count;
1440 bool incomplete;
1441};
1442
1443struct ZigTypeEnum {
1444 AstNode *decl_node;
1445 TypeEnumField *fields;
1446 ZigType *tag_int_type;
1447
1448 ScopeDecls *decls_scope;
1449
1450 LLVMValueRef name_function;
1451
1452 HashMap<Buf *, TypeEnumField *, buf_hash, buf_eql_buf> fields_by_name;
1453 uint32_t src_field_count;
1454
1455 ContainerLayout layout;
1456 ResolveStatus resolve_status;
1457
1458 bool has_explicit_tag_type;
1459 bool non_exhaustive;
1460 bool resolve_loop_flag;
1461};
1462
1463uint32_t type_ptr_hash(const ZigType *ptr);
1464bool type_ptr_eql(const ZigType *a, const ZigType *b);
1465
1466uint32_t pkg_ptr_hash(const ZigPackage *ptr);
1467bool pkg_ptr_eql(const ZigPackage *a, const ZigPackage *b);
1468
1469uint32_t tld_ptr_hash(const Tld *ptr);
1470bool tld_ptr_eql(const Tld *a, const Tld *b);
1471
1472uint32_t node_ptr_hash(const AstNode *ptr);
1473bool node_ptr_eql(const AstNode *a, const AstNode *b);
1474
1475uint32_t fn_ptr_hash(const ZigFn *ptr);
1476bool fn_ptr_eql(const ZigFn *a, const ZigFn *b);
1477
1478uint32_t err_ptr_hash(const ErrorTableEntry *ptr);
1479bool err_ptr_eql(const ErrorTableEntry *a, const ErrorTableEntry *b);
1480
1481struct ZigTypeUnion {
1482 AstNode *decl_node;
1483 TypeUnionField *fields;
1484 ScopeDecls *decls_scope;
1485 HashMap<Buf *, TypeUnionField *, buf_hash, buf_eql_buf> fields_by_name;
1486 ZigType *tag_type; // always an enum or null
1487 LLVMTypeRef union_llvm_type;
1488 TypeUnionField *most_aligned_union_member;
1489 size_t gen_union_index;
1490 size_t gen_tag_index;
1491 size_t union_abi_size;
1492
1493 uint32_t src_field_count;
1494 uint32_t gen_field_count;
1495
1496 ContainerLayout layout;
1497 ResolveStatus resolve_status;
1498
1499 bool have_explicit_tag_type;
1500 // whether any of the fields require comptime
1501 // the value is not valid until zero_bits_known == true
1502 bool requires_comptime;
1503 bool resolve_loop_flag_zero_bits;
1504 bool resolve_loop_flag_other;
1505};
1506
1507struct FnGenParamInfo {
1508 size_t src_index;
1509 size_t gen_index;
1510 bool is_byval;
1511 ZigType *type;
1512};
1513
1514struct ZigTypeFn {
1515 FnTypeId fn_type_id;
1516 bool is_generic;
1517 ZigType *gen_return_type;
1518 size_t gen_param_count;
1519 FnGenParamInfo *gen_param_info;
1520
1521 LLVMTypeRef raw_type_ref;
1522 ZigLLVMDIType *raw_di_type;
1523
1524 ZigType *bound_fn_parent;
1525};
1526
1527struct ZigTypeBoundFn {
1528 ZigType *fn_type;
1529};
1530
1531// Needs to have the same memory layout as ZigTypeArray
1532struct ZigTypeVector {
1533 // The type must be a pointer, integer, bool, or float
1534 ZigType *elem_type;
1535 uint64_t len;
1536 size_t padding;
1537};
1538
1539// A lot of code is relying on ZigTypeArray and ZigTypeVector having the same layout/size
1540static_assert(sizeof(ZigTypeVector) == sizeof(ZigTypeArray), "Size of ZigTypeVector and ZigTypeArray do not match!");
1541
1542enum ZigTypeId {
1543 ZigTypeIdInvalid,
1544 ZigTypeIdMetaType,
1545 ZigTypeIdVoid,
1546 ZigTypeIdBool,
1547 ZigTypeIdUnreachable,
1548 ZigTypeIdInt,
1549 ZigTypeIdFloat,
1550 ZigTypeIdPointer,
1551 ZigTypeIdArray,
1552 ZigTypeIdStruct,
1553 ZigTypeIdComptimeFloat,
1554 ZigTypeIdComptimeInt,
1555 ZigTypeIdUndefined,
1556 ZigTypeIdNull,
1557 ZigTypeIdOptional,
1558 ZigTypeIdErrorUnion,
1559 ZigTypeIdErrorSet,
1560 ZigTypeIdEnum,
1561 ZigTypeIdUnion,
1562 ZigTypeIdFn,
1563 ZigTypeIdBoundFn,
1564 ZigTypeIdOpaque,
1565 ZigTypeIdFnFrame,
1566 ZigTypeIdAnyFrame,
1567 ZigTypeIdVector,
1568 ZigTypeIdEnumLiteral,
1569};
1570
1571enum OnePossibleValue {
1572 OnePossibleValueInvalid,
1573 OnePossibleValueNo,
1574 OnePossibleValueYes,
1575};
1576
1577struct ZigTypeOpaque {
1578 AstNode *decl_node;
1579 Buf *bare_name;
1580
1581 ScopeDecls *decls_scope;
1582};
1583
1584struct ZigTypeFnFrame {
1585 ZigFn *fn;
1586 ZigType *locals_struct;
1587
1588 // This is set to the type that resolving the frame currently depends on, null if none.
1589 // It's for generating a helpful error message.
1590 ZigType *resolve_loop_type;
1591 AstNode *resolve_loop_src_node;
1592 bool reported_loop_err;
1593};
1594
1595struct ZigTypeAnyFrame {
1596 ZigType *result_type; // null if `anyframe` instead of `anyframe->T`
1597 LLVMTypeRef struct_llvm_ty;
1598};
1599
1600struct ZigType {
1601 ZigTypeId id;
1602 Buf name;
1603
1604 // These are not supposed to be accessed directly. They're
1605 // null during semantic analysis, memoized with get_llvm_type
1606 // get_llvm_c_abi_type and get_llvm_di_type
1607 LLVMTypeRef llvm_type;
1608 LLVMTypeRef llvm_c_abi_type;
1609 ZigLLVMDIType *llvm_di_type;
1610
1611 union {
1612 ZigTypePointer pointer;
1613 ZigTypeInt integral;
1614 ZigTypeFloat floating;
1615 ZigTypeArray array;
1616 ZigTypeStruct structure;
1617 ZigTypeOptional maybe;
1618 ZigTypeErrorUnion error_union;
1619 ZigTypeErrorSet error_set;
1620 ZigTypeEnum enumeration;
1621 ZigTypeUnion unionation;
1622 ZigTypeFn fn;
1623 ZigTypeBoundFn bound_fn;
1624 ZigTypeVector vector;
1625 ZigTypeOpaque opaque;
1626 ZigTypeFnFrame frame;
1627 ZigTypeAnyFrame any_frame;
1628 } data;
1629
1630 // use these fields to make sure we don't duplicate type table entries for the same type
1631 ZigType *pointer_parent[2]; // [0 - mut, 1 - const]
1632 ZigType *optional_parent;
1633 ZigType *any_frame_parent;
1634 // If we generate a constant name value for this type, we memoize it here.
1635 // The type of this is array
1636 ZigValue *cached_const_name_val;
1637
1638 OnePossibleValue one_possible_value;
1639 // Known after ResolveStatusAlignmentKnown.
1640 uint32_t abi_align;
1641 // The offset in bytes between consecutive array elements of this type. Known
1642 // after ResolveStatusSizeKnown.
1643 size_t abi_size;
1644 // Number of bits of information in this type. Known after ResolveStatusSizeKnown.
1645 size_t size_in_bits;
1646};
1647
1648enum FnAnalState {
1649 FnAnalStateReady,
1650 FnAnalStateProbing,
1651 FnAnalStateComplete,
1652 FnAnalStateInvalid,
1653};
1654
1655struct GlobalExport {
1656 Buf name;
1657 GlobalLinkageId linkage;
1658};
1659
1660struct ZigFn {
1661 LLVMValueRef llvm_value;
1662 LLVMValueRef abi_return_value; // alloca used when converting at SysV ABI boundaries
1663 const char *llvm_name;
1664 AstNode *proto_node;
1665 AstNode *body_node;
1666 ScopeFnDef *fndef_scope; // parent should be the top level decls or container decls
1667 Scope *child_scope; // parent is scope for last parameter
1668 ScopeBlock *def_scope; // parent is child_scope
1669 Buf symbol_name;
1670 // This is the function type assuming the function does not suspend.
1671 // Note that for an async function, this can be shared with non-async functions. So the value here
1672 // should only be read for things in common between non-async and async function types.
1673 ZigType *type_entry;
1674 // For normal functions one could use the type_entry->raw_type_ref and type_entry->raw_di_type.
1675 // However for functions that suspend, those values could possibly be their non-suspending equivalents.
1676 // So these values should be preferred.
1677 LLVMTypeRef raw_type_ref;
1678 ZigLLVMDIType *raw_di_type;
1679
1680 ZigType *frame_type;
1681 // in the case of normal functions this is the implicit return type
1682 // in the case of async functions this is the implicit return type according to the
1683 // zig source code, not according to zig ir
1684 ZigType *src_implicit_return_type;
1685 Stage1Zir *stage1_zir;
1686 Stage1Air analyzed_executable;
1687 size_t branch_quota;
1688 AstNode **param_source_nodes;
1689 Buf **param_names;
1690 Stage1AirInst *err_code_spill;
1691 AstNode *assumed_non_async;
1692
1693 AstNode *fn_no_inline_set_node;
1694 AstNode *fn_static_eval_set_node;
1695
1696 ZigList<Stage1AirInstAlloca *> alloca_gen_list;
1697 ZigList<ZigVar *> variable_list;
1698
1699 Buf *section_name;
1700 AstNode *set_alignstack_node;
1701
1702 AstNode *set_cold_node;
1703 const AstNode *inferred_async_node;
1704 ZigFn *inferred_async_fn;
1705 AstNode *non_async_node;
1706
1707 ZigList<GlobalExport> export_list;
1708 ZigList<Stage1AirInstCall *> call_list;
1709 ZigList<Stage1AirInstAwait *> await_list;
1710
1711 LLVMValueRef valgrind_client_request_array;
1712
1713 FnAnalState anal_state;
1714
1715 uint32_t align_bytes;
1716 uint32_t alignstack_value;
1717
1718 bool calls_or_awaits_errorable_fn;
1719 bool is_cold;
1720 bool is_noinline;
1721};
1722
1723static inline bool fn_is_test(const ZigFn *fn) {
1724 return fn->proto_node->type == NodeTypeTestDecl;
1725}
1726
1727uint32_t fn_table_entry_hash(ZigFn*);
1728bool fn_table_entry_eql(ZigFn *a, ZigFn *b);
1729
1730enum BuiltinFnId {
1731 BuiltinFnIdInvalid,
1732 BuiltinFnIdMemcpy,
1733 BuiltinFnIdMemset,
1734 BuiltinFnIdSizeof,
1735 BuiltinFnIdAlignOf,
1736 BuiltinFnIdField,
1737 BuiltinFnIdTypeInfo,
1738 BuiltinFnIdType,
1739 BuiltinFnIdHasField,
1740 BuiltinFnIdTypeof,
1741 BuiltinFnIdAddWithOverflow,
1742 BuiltinFnIdSubWithOverflow,
1743 BuiltinFnIdMulWithOverflow,
1744 BuiltinFnIdShlWithOverflow,
1745 BuiltinFnIdMulAdd,
1746 BuiltinFnIdCInclude,
1747 BuiltinFnIdCDefine,
1748 BuiltinFnIdCUndef,
1749 BuiltinFnIdCompileErr,
1750 BuiltinFnIdCompileLog,
1751 BuiltinFnIdCtz,
1752 BuiltinFnIdClz,
1753 BuiltinFnIdPopCount,
1754 BuiltinFnIdBswap,
1755 BuiltinFnIdBitReverse,
1756 BuiltinFnIdImport,
1757 BuiltinFnIdCImport,
1758 BuiltinFnIdErrName,
1759 BuiltinFnIdBreakpoint,
1760 BuiltinFnIdReturnAddress,
1761 BuiltinFnIdEmbedFile,
1762 BuiltinFnIdCmpxchgWeak,
1763 BuiltinFnIdCmpxchgStrong,
1764 BuiltinFnIdFence,
1765 BuiltinFnIdDivExact,
1766 BuiltinFnIdDivTrunc,
1767 BuiltinFnIdDivFloor,
1768 BuiltinFnIdRem,
1769 BuiltinFnIdMod,
1770 BuiltinFnIdSqrt,
1771 BuiltinFnIdSin,
1772 BuiltinFnIdCos,
1773 BuiltinFnIdTan,
1774 BuiltinFnIdExp,
1775 BuiltinFnIdExp2,
1776 BuiltinFnIdLog,
1777 BuiltinFnIdLog2,
1778 BuiltinFnIdLog10,
1779 BuiltinFnIdFabs,
1780 BuiltinFnIdFloor,
1781 BuiltinFnIdCeil,
1782 BuiltinFnIdTrunc,
1783 BuiltinFnIdNearbyInt,
1784 BuiltinFnIdRound,
1785 BuiltinFnIdTruncate,
1786 BuiltinFnIdIntCast,
1787 BuiltinFnIdFloatCast,
1788 BuiltinFnIdErrSetCast,
1789 BuiltinFnIdIntToFloat,
1790 BuiltinFnIdFloatToInt,
1791 BuiltinFnIdBoolToInt,
1792 BuiltinFnIdErrToInt,
1793 BuiltinFnIdIntToErr,
1794 BuiltinFnIdEnumToInt,
1795 BuiltinFnIdIntToEnum,
1796 BuiltinFnIdVectorType,
1797 BuiltinFnIdShuffle,
1798 BuiltinFnIdSelect,
1799 BuiltinFnIdSplat,
1800 BuiltinFnIdSetCold,
1801 BuiltinFnIdSetRuntimeSafety,
1802 BuiltinFnIdSetFloatMode,
1803 BuiltinFnIdTypeName,
1804 BuiltinFnIdPanic,
1805 BuiltinFnIdPtrCast,
1806 BuiltinFnIdBitCast,
1807 BuiltinFnIdIntToPtr,
1808 BuiltinFnIdPtrToInt,
1809 BuiltinFnIdTagName,
1810 BuiltinFnIdFieldParentPtr,
1811 BuiltinFnIdOffsetOf,
1812 BuiltinFnIdBitOffsetOf,
1813 BuiltinFnIdAsyncCall,
1814 BuiltinFnIdShlExact,
1815 BuiltinFnIdShrExact,
1816 BuiltinFnIdSetEvalBranchQuota,
1817 BuiltinFnIdAlignCast,
1818 BuiltinFnIdThis,
1819 BuiltinFnIdSetAlignStack,
1820 BuiltinFnIdExport,
1821 BuiltinFnIdExtern,
1822 BuiltinFnIdErrorReturnTrace,
1823 BuiltinFnIdAtomicRmw,
1824 BuiltinFnIdAtomicLoad,
1825 BuiltinFnIdAtomicStore,
1826 BuiltinFnIdHasDecl,
1827 BuiltinFnIdUnionInit,
1828 BuiltinFnIdFrameAddress,
1829 BuiltinFnIdFrameType,
1830 BuiltinFnIdFrameHandle,
1831 BuiltinFnIdFrameSize,
1832 BuiltinFnIdAs,
1833 BuiltinFnIdCall,
1834 BuiltinFnIdBitSizeof,
1835 BuiltinFnIdWasmMemorySize,
1836 BuiltinFnIdWasmMemoryGrow,
1837 BuiltinFnIdSrc,
1838 BuiltinFnIdReduce,
1839 BuiltinFnIdMaximum,
1840 BuiltinFnIdMinimum,
1841 BuiltinFnIdPrefetch,
1842 BuiltinFnIdAddrSpaceCast,
1843};
1844
1845struct BuiltinFnEntry {
1846 BuiltinFnId id;
1847 Buf name;
1848 size_t param_count;
1849};
1850
1851enum PanicMsgId {
1852 PanicMsgIdUnreachable,
1853 PanicMsgIdBoundsCheckFailure,
1854 PanicMsgIdCastNegativeToUnsigned,
1855 PanicMsgIdCastTruncatedData,
1856 PanicMsgIdIntegerOverflow,
1857 PanicMsgIdShlOverflowedBits,
1858 PanicMsgIdShrOverflowedBits,
1859 PanicMsgIdDivisionByZero,
1860 PanicMsgIdRemainderDivisionByZero,
1861 PanicMsgIdExactDivisionRemainder,
1862 PanicMsgIdUnwrapOptionalFail,
1863 PanicMsgIdInvalidErrorCode,
1864 PanicMsgIdIncorrectAlignment,
1865 PanicMsgIdBadUnionField,
1866 PanicMsgIdBadEnumValue,
1867 PanicMsgIdFloatToInt,
1868 PanicMsgIdPtrCastNull,
1869 PanicMsgIdBadResume,
1870 PanicMsgIdBadAwait,
1871 PanicMsgIdBadReturn,
1872 PanicMsgIdResumedAnAwaitingFn,
1873 PanicMsgIdFrameTooSmall,
1874 PanicMsgIdResumedFnPendingAwait,
1875 PanicMsgIdBadNoSuspendCall,
1876 PanicMsgIdResumeNotSuspendedFn,
1877 PanicMsgIdBadSentinel,
1878 PanicMsgIdShxTooBigRhs,
1879
1880 PanicMsgIdCount,
1881};
1882
1883uint32_t fn_eval_hash(Scope*);
1884bool fn_eval_eql(Scope *a, Scope *b);
1885
1886struct TypeId {
1887 ZigTypeId id;
1888
1889 union {
1890 struct {
1891 CodeGen *codegen;
1892 ZigType *child_type;
1893 InferredStructField *inferred_struct_field;
1894 ZigValue *sentinel;
1895 PtrLen ptr_len;
1896 uint32_t alignment;
1897
1898 uint32_t bit_offset_in_host;
1899 uint32_t host_int_bytes;
1900
1901 uint32_t vector_index;
1902 bool is_const;
1903 bool is_volatile;
1904 bool allow_zero;
1905 } pointer;
1906 struct {
1907 CodeGen *codegen;
1908 ZigType *child_type;
1909 uint64_t size;
1910 ZigValue *sentinel;
1911 } array;
1912 struct {
1913 bool is_signed;
1914 uint32_t bit_count;
1915 } integer;
1916 struct {
1917 ZigType *err_set_type;
1918 ZigType *payload_type;
1919 } error_union;
1920 struct {
1921 ZigType *elem_type;
1922 uint32_t len;
1923 } vector;
1924 } data;
1925};
1926
1927uint32_t type_id_hash(TypeId const *);
1928bool type_id_eql(TypeId const *a, TypeId const *b);
1929
1930enum ZigLLVMFnId {
1931 ZigLLVMFnIdCtz,
1932 ZigLLVMFnIdClz,
1933 ZigLLVMFnIdPopCount,
1934 ZigLLVMFnIdOverflowArithmetic,
1935 ZigLLVMFnIdFMA,
1936 ZigLLVMFnIdFloatOp,
1937 ZigLLVMFnIdBswap,
1938 ZigLLVMFnIdBitReverse,
1939};
1940
1941// There are a bunch of places in code that rely on these values being in
1942// exactly this order.
1943enum AddSubMul {
1944 AddSubMulAdd = 0,
1945 AddSubMulSub = 1,
1946 AddSubMulMul = 2,
1947};
1948
1949struct ZigLLVMFnKey {
1950 ZigLLVMFnId id;
1951
1952 union {
1953 struct {
1954 uint32_t bit_count;
1955 uint32_t vector_len; // 0 means not a vector
1956 } ctz;
1957 struct {
1958 uint32_t bit_count;
1959 uint32_t vector_len; // 0 means not a vector
1960 } clz;
1961 struct {
1962 uint32_t bit_count;
1963 uint32_t vector_len; // 0 means not a vector
1964 } pop_count;
1965 struct {
1966 BuiltinFnId op;
1967 uint32_t bit_count;
1968 uint32_t vector_len; // 0 means not a vector
1969 } floating;
1970 struct {
1971 AddSubMul add_sub_mul;
1972 uint32_t bit_count;
1973 uint32_t vector_len; // 0 means not a vector
1974 bool is_signed;
1975 } overflow_arithmetic;
1976 struct {
1977 uint32_t bit_count;
1978 uint32_t vector_len; // 0 means not a vector
1979 } bswap;
1980 struct {
1981 uint32_t bit_count;
1982 uint32_t vector_len; // 0 means not a vector
1983 } bit_reverse;
1984 } data;
1985};
1986
1987uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey const *);
1988bool zig_llvm_fn_key_eql(ZigLLVMFnKey const *a, ZigLLVMFnKey const *b);
1989
1990struct TimeEvent {
1991 double time;
1992 const char *name;
1993};
1994
1995struct CFile {
1996 ZigList<const char *> args;
1997 const char *source_path;
1998 const char *preprocessor_only_basename;
1999};
2000
2001struct CodeGen {
2002 // Other code depends on this being first.
2003 ZigStage1 stage1;
2004
2005 // arena allocator destroyed just prior to codegen emit
2006 heap::ArenaAllocator *pass1_arena;
2007
2008 //////////////////////////// Runtime State
2009 LLVMModuleRef module;
2010 ZigList<ErrorMsg*> errors;
2011 ErrorMsg *trace_err;
2012 LLVMBuilderRef builder;
2013 ZigLLVMDIBuilder *dbuilder;
2014 ZigLLVMDICompileUnit *compile_unit;
2015 ZigLLVMDIFile *compile_unit_file;
2016 LLVMTargetDataRef target_data_ref;
2017 LLVMTargetMachineRef target_machine;
2018 ZigLLVMDIFile *dummy_di_file;
2019 LLVMValueRef cur_ret_ptr;
2020 LLVMValueRef cur_frame_ptr;
2021 LLVMValueRef cur_fn_val;
2022 LLVMValueRef cur_async_switch_instr;
2023 LLVMValueRef cur_async_resume_index_ptr;
2024 LLVMValueRef cur_async_awaiter_ptr;
2025 LLVMBasicBlockRef cur_preamble_llvm_block;
2026 size_t cur_resume_block_count;
2027 LLVMValueRef cur_err_ret_trace_val_arg;
2028 LLVMValueRef cur_err_ret_trace_val_stack;
2029 LLVMValueRef cur_bad_not_suspended_index;
2030 LLVMValueRef memcpy_fn_val;
2031 LLVMValueRef memset_fn_val;
2032 LLVMValueRef trap_fn_val;
2033 LLVMValueRef return_address_fn_val;
2034 LLVMValueRef frame_address_fn_val;
2035 LLVMValueRef add_error_return_trace_addr_fn_val;
2036 LLVMValueRef stacksave_fn_val;
2037 LLVMValueRef stackrestore_fn_val;
2038 LLVMValueRef write_register_fn_val;
2039 LLVMValueRef merge_err_ret_traces_fn_val;
2040 LLVMValueRef sp_md_node;
2041 LLVMValueRef err_name_table;
2042 LLVMValueRef safety_crash_err_fn;
2043 LLVMValueRef return_err_fn;
2044 LLVMValueRef wasm_memory_size;
2045 LLVMValueRef wasm_memory_grow;
2046 LLVMValueRef prefetch;
2047 LLVMTypeRef anyframe_fn_type;
2048 LLVMTypeRef any_frame_header_llvm_ty;
2049
2050 // reminder: hash tables must be initialized before use
2051 HashMap<Buf *, ZigType *, buf_hash, buf_eql_buf> import_table;
2052 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
2053 HashMap<Buf *, ZigType *, buf_hash, buf_eql_buf> primitive_type_table;
2054 HashMap<TypeId, ZigType *, type_id_hash, type_id_eql> type_table;
2055 HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
2056 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
2057 HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
2058 HashMap<Scope *, ZigValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
2059 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
2060 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> exported_symbol_names;
2061 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_symbol_names;
2062 HashMap<Buf *, ZigValue *, buf_hash, buf_eql_buf> string_literals_table;
2063 HashMap<const ZigType *, ZigValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
2064 HashMap<const ZigType *, ZigValue *, type_ptr_hash, type_ptr_eql> one_possible_values;
2065
2066 ZigList<Tld *> resolve_queue;
2067 size_t resolve_queue_index;
2068 ZigList<TimeEvent> timing_events;
2069 ZigList<ZigFn *> inline_fns;
2070 ZigList<ZigFn *> test_fns;
2071 ZigList<ErrorTableEntry *> errors_by_index;
2072 size_t largest_err_name_len;
2073 ZigList<ZigType *> type_resolve_stack;
2074
2075 ZigPackage *std_package;
2076 ZigPackage *test_runner_package;
2077 ZigPackage *compile_var_package;
2078 ZigPackage *root_pkg; // @import("root")
2079 ZigPackage *main_pkg; // usually same as root_pkg, except for `zig test`
2080 ZigType *compile_var_import;
2081 ZigType *root_import;
2082 ZigType *start_import;
2083 ZigType *std_builtin_import;
2084
2085 struct {
2086 ZigType *entry_bool;
2087 ZigType *entry_c_int[CIntTypeCount];
2088 ZigType *entry_c_longdouble;
2089 ZigType *entry_anyopaque;
2090 ZigType *entry_u8;
2091 ZigType *entry_u16;
2092 ZigType *entry_u32;
2093 ZigType *entry_u29;
2094 ZigType *entry_u64;
2095 ZigType *entry_i8;
2096 ZigType *entry_i32;
2097 ZigType *entry_i64;
2098 ZigType *entry_isize;
2099 ZigType *entry_usize;
2100 ZigType *entry_f16;
2101 ZigType *entry_f32;
2102 ZigType *entry_f64;
2103 ZigType *entry_f80;
2104 ZigType *entry_f128;
2105 ZigType *entry_void;
2106 ZigType *entry_unreachable;
2107 ZigType *entry_type;
2108 ZigType *entry_invalid;
2109 ZigType *entry_block;
2110 ZigType *entry_num_lit_int;
2111 ZigType *entry_num_lit_float;
2112 ZigType *entry_undef;
2113 ZigType *entry_null;
2114 ZigType *entry_anytype;
2115 ZigType *entry_global_error_set;
2116 ZigType *entry_enum_literal;
2117 ZigType *entry_any_frame;
2118 ZigType *entry_opt_ptr_const_anyopaque;
2119 } builtin_types;
2120
2121 struct Intern {
2122 ZigValue x_undefined;
2123 ZigValue x_void;
2124 ZigValue x_null;
2125 ZigValue x_unreachable;
2126 ZigValue zero_byte;
2127
2128 ZigValue *for_undefined();
2129 ZigValue *for_void();
2130 ZigValue *for_null();
2131 ZigValue *for_unreachable();
2132 ZigValue *for_zero_byte();
2133 } intern;
2134
2135 ZigType *align_amt_type;
2136 ZigType *stack_trace_type;
2137 ZigType *err_tag_type;
2138 ZigType *test_fn_type;
2139
2140 Buf llvm_triple_str;
2141 Buf global_asm;
2142 Buf o_file_output_path;
2143 Buf h_file_output_path;
2144 Buf asm_file_output_path;
2145 Buf llvm_ir_file_output_path;
2146 Buf bitcode_file_output_path;
2147
2148 Buf *builtin_zig_path;
2149
2150 Stage1ZirInst *invalid_inst_src;
2151 Stage1AirInst *invalid_inst_gen;
2152 Stage1AirInst *unreach_instruction;
2153
2154 ZigValue panic_msg_vals[PanicMsgIdCount];
2155
2156 // The function definitions this module includes.
2157 ZigList<ZigFn *> fn_defs;
2158 size_t fn_defs_index;
2159 ZigList<TldVar *> global_vars;
2160
2161 ZigFn *cur_fn;
2162 ZigFn *panic_fn;
2163
2164 ZigFn *largest_frame_fn;
2165
2166 Stage2ProgressNode *main_progress_node;
2167 Stage2ProgressNode *sub_progress_node;
2168
2169 ErrColor err_color;
2170 uint32_t next_unresolved_index;
2171 unsigned pointer_size_bytes;
2172 bool is_big_endian;
2173 bool have_err_ret_tracing;
2174 bool verbose_ir;
2175 bool verbose_llvm_ir;
2176 bool verbose_cimport;
2177 bool verbose_llvm_cpu_features;
2178 bool error_during_imports;
2179 bool generate_error_name_table;
2180 bool enable_time_report;
2181 bool enable_stack_report;
2182 bool reported_bad_link_libc_error;
2183 bool need_frame_size_prefix_data;
2184 bool link_libc;
2185 bool link_libcpp;
2186
2187 BuildMode build_mode;
2188 const ZigTarget *zig_target;
2189 TargetSubsystem subsystem; // careful using this directly; see detect_subsystem
2190 CodeModel code_model;
2191 bool strip_debug_symbols;
2192 bool is_test_build;
2193 bool is_single_threaded;
2194 bool have_pic;
2195 bool have_pie;
2196 bool have_lto;
2197 bool unwind_tables;
2198 bool link_mode_dynamic;
2199 bool dll_export_fns;
2200 bool have_stack_probing;
2201 bool red_zone;
2202 bool omit_frame_pointer;
2203 bool function_sections;
2204 bool include_compiler_rt;
2205 bool test_is_evented;
2206 bool valgrind_enabled;
2207 bool tsan_enabled;
2208
2209 Buf *root_out_name;
2210 Buf *test_filter;
2211 Buf *test_name_prefix;
2212 Buf *zig_lib_dir;
2213 Buf *zig_std_dir;
2214};
2215
2216struct ZigVar {
2217 const char *name;
2218 ZigValue *const_value;
2219 ZigType *var_type;
2220 LLVMValueRef value_ref;
2221 Stage1ZirInst *is_comptime;
2222 Stage1AirInst *ptr_instruction;
2223 // which node is the declaration of the variable
2224 AstNode *decl_node;
2225 ZigLLVMDILocalVariable *di_loc_var;
2226 size_t src_arg_index;
2227 Scope *parent_scope;
2228 Scope *child_scope;
2229 LLVMValueRef param_value_ref;
2230
2231 Buf *section_name;
2232
2233 // In an inline loop, multiple variables may be created,
2234 // In this case, a reference to a variable should follow
2235 // this pointer to the redefined variable.
2236 ZigVar *next_var;
2237
2238 ZigList<GlobalExport> export_list;
2239
2240 uint32_t align_bytes;
2241 uint32_t ref_count;
2242
2243 bool shadowable;
2244 bool src_is_const;
2245 bool gen_is_const;
2246 bool is_thread_local;
2247 bool is_comptime_memoized;
2248 bool is_comptime_memoized_value;
2249 bool did_the_decl_codegen;
2250};
2251
2252struct ErrorTableEntry {
2253 Buf name;
2254 uint32_t value;
2255 AstNode *decl_node;
2256 ErrorTableEntry *other; // null, or another error decl that was merged into this
2257 ZigType *set_with_only_this_in_it;
2258 // If we generate a constant error name value for this error, we memoize it here.
2259 // The type of this is array
2260 ZigValue *cached_error_name_val;
2261};
2262
2263enum ScopeId {
2264 ScopeIdDecls,
2265 ScopeIdBlock,
2266 ScopeIdDefer,
2267 ScopeIdDeferExpr,
2268 ScopeIdVarDecl,
2269 ScopeIdCImport,
2270 ScopeIdLoop,
2271 ScopeIdSuspend,
2272 ScopeIdFnDef,
2273 ScopeIdCompTime,
2274 ScopeIdRuntime,
2275 ScopeIdTypeOf,
2276 ScopeIdExpr,
2277 ScopeIdNoSuspend,
2278};
2279
2280struct Scope {
2281 CodeGen *codegen;
2282 AstNode *source_node;
2283
2284 // if the scope has a parent, this is it
2285 Scope *parent;
2286
2287 ZigLLVMDIScope *di_scope;
2288 ScopeId id;
2289};
2290
2291// This scope comes from global declarations or from
2292// declarations in a container declaration
2293// NodeTypeContainerDecl
2294struct ScopeDecls {
2295 Scope base;
2296
2297 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> decl_table;
2298 ZigList<TldUsingNamespace *> use_decls;
2299 AstNode *safety_set_node;
2300 AstNode *fast_math_set_node;
2301 ZigType *import;
2302 // If this is a scope from a container, this is the type entry, otherwise null
2303 ZigType *container_type;
2304 Buf *bare_name;
2305
2306 bool safety_off;
2307 bool fast_math_on;
2308 bool any_imports_failed;
2309};
2310
2311enum LVal {
2312 LValNone,
2313 LValPtr,
2314 LValAssign,
2315};
2316
2317// This scope comes from a block expression in user code.
2318// NodeTypeBlock
2319struct ScopeBlock {
2320 Scope base;
2321
2322 Buf *name;
2323 Stage1ZirBasicBlock *end_block;
2324 Stage1ZirInst *is_comptime;
2325 ResultLocPeerParent *peer_parent;
2326 ZigList<Stage1ZirInst *> *incoming_values;
2327 ZigList<Stage1ZirBasicBlock *> *incoming_blocks;
2328
2329 AstNode *safety_set_node;
2330 AstNode *fast_math_set_node;
2331
2332 LVal lval;
2333 bool safety_off;
2334 bool fast_math_on;
2335 bool name_used;
2336};
2337
2338// This scope is created from every defer expression.
2339// It's the code following the defer statement.
2340// NodeTypeDefer
2341struct ScopeDefer {
2342 Scope base;
2343};
2344
2345// This scope is created from every defer expression.
2346// It's the parent of the defer expression itself.
2347// NodeTypeDefer
2348struct ScopeDeferExpr {
2349 Scope base;
2350
2351 bool reported_err;
2352};
2353
2354// This scope is created for every variable declaration inside an IrExecutable
2355// NodeTypeVariableDeclaration, NodeTypeParamDecl
2356struct ScopeVarDecl {
2357 Scope base;
2358
2359 // The variable that creates this scope
2360 ZigVar *var;
2361};
2362
2363// This scope is created for a @cImport
2364// NodeTypeFnCallExpr
2365struct ScopeCImport {
2366 Scope base;
2367
2368 Buf buf;
2369};
2370
2371// This scope is created for a loop such as for or while in order to
2372// make break and continue statements work.
2373// NodeTypeForExpr or NodeTypeWhileExpr
2374struct ScopeLoop {
2375 Scope base;
2376
2377 LVal lval;
2378 Buf *name;
2379 Stage1ZirBasicBlock *break_block;
2380 Stage1ZirBasicBlock *continue_block;
2381 Stage1ZirInst *is_comptime;
2382 ZigList<Stage1ZirInst *> *incoming_values;
2383 ZigList<Stage1ZirBasicBlock *> *incoming_blocks;
2384 ResultLocPeerParent *peer_parent;
2385 ScopeExpr *spill_scope;
2386
2387 bool name_used;
2388};
2389
2390// This scope blocks certain things from working such as comptime continue
2391// inside a runtime if expression.
2392// NodeTypeIfBoolExpr, NodeTypeWhileExpr, NodeTypeForExpr
2393struct ScopeRuntime {
2394 Scope base;
2395
2396 Stage1ZirInst *is_comptime;
2397};
2398
2399// This scope is created for a suspend block in order to have labeled
2400// suspend for breaking out of a suspend and for detecting if a suspend
2401// block is inside a suspend block.
2402struct ScopeSuspend {
2403 Scope base;
2404
2405 bool reported_err;
2406};
2407
2408// This scope is created for a comptime expression.
2409// NodeTypeCompTime, NodeTypeSwitchExpr
2410struct ScopeCompTime {
2411 Scope base;
2412};
2413
2414// This scope is created for a nosuspend expression.
2415// NodeTypeNoSuspend
2416struct ScopeNoSuspend {
2417 Scope base;
2418};
2419
2420// This scope is created for a function definition.
2421// NodeTypeFnDef
2422struct ScopeFnDef {
2423 Scope base;
2424
2425 ZigFn *fn_entry;
2426};
2427
2428// This scope is created for a @TypeOf.
2429// All runtime side-effects are elided within it.
2430// NodeTypeFnCallExpr
2431struct ScopeTypeOf {
2432 Scope base;
2433};
2434
2435enum MemoizedBool {
2436 MemoizedBoolUnknown,
2437 MemoizedBoolFalse,
2438 MemoizedBoolTrue,
2439};
2440
2441// This scope is created for each expression.
2442// It's used to identify when an instruction needs to be spilled,
2443// so that it can be accessed after a suspend point.
2444struct ScopeExpr {
2445 Scope base;
2446
2447 ScopeExpr **children_ptr;
2448 size_t children_len;
2449
2450 MemoizedBool need_spill;
2451 // This is a hack. I apologize for this, I need this to work so that I
2452 // can make progress on other fronts. I'll pay off this tech debt eventually.
2453 bool spill_harder;
2454};
2455
2456// synchronized with code in define_builtin_compile_vars
2457enum AtomicOrder {
2458 AtomicOrderUnordered,
2459 AtomicOrderMonotonic,
2460 AtomicOrderAcquire,
2461 AtomicOrderRelease,
2462 AtomicOrderAcqRel,
2463 AtomicOrderSeqCst,
2464};
2465
2466// synchronized with code in define_builtin_compile_vars
2467enum ReduceOp {
2468 ReduceOp_and,
2469 ReduceOp_or,
2470 ReduceOp_xor,
2471 ReduceOp_min,
2472 ReduceOp_max,
2473 ReduceOp_add,
2474 ReduceOp_mul,
2475};
2476
2477// synchronized with the code in define_builtin_compile_vars
2478enum AtomicRmwOp {
2479 AtomicRmwOp_xchg,
2480 AtomicRmwOp_add,
2481 AtomicRmwOp_sub,
2482 AtomicRmwOp_and,
2483 AtomicRmwOp_nand,
2484 AtomicRmwOp_or,
2485 AtomicRmwOp_xor,
2486 AtomicRmwOp_max,
2487 AtomicRmwOp_min,
2488};
2489
2490// A basic block contains no branching. Branches send control flow
2491// to another basic block.
2492// Phi instructions must be first in a basic block.
2493// The last instruction in a basic block must be of type unreachable.
2494struct Stage1ZirBasicBlock {
2495 ZigList<Stage1ZirInst *> instruction_list;
2496 Stage1AirBasicBlock *child;
2497 Scope *scope;
2498 const char *name_hint;
2499 Stage1ZirInst *suspend_instruction_ref;
2500
2501 uint32_t ref_count;
2502 uint32_t index; // index into the basic block list
2503
2504 uint32_t debug_id;
2505 bool suspended;
2506 bool in_resume_stack;
2507};
2508
2509struct Stage1AirBasicBlock {
2510 ZigList<Stage1AirInst *> instruction_list;
2511 Scope *scope;
2512 const char *name_hint;
2513 LLVMBasicBlockRef llvm_block;
2514 LLVMBasicBlockRef llvm_exit_block;
2515 // The instruction that referenced this basic block and caused us to
2516 // analyze the basic block. If the same instruction wants us to emit
2517 // the same basic block, then we re-generate it instead of saving it.
2518 Stage1ZirInst *ref_instruction;
2519 // When this is non-null, a branch to this basic block is only allowed
2520 // if the branch is comptime. The instruction points to the reason
2521 // the basic block must be comptime.
2522 AstNode *must_be_comptime_source_node;
2523
2524 uint32_t debug_id;
2525 bool already_appended;
2526};
2527
2528// Src instructions are generated by ir_gen_* functions in ir.cpp from AST.
2529// ir_analyze_* functions consume Src instructions and produce Gen instructions.
2530// Src instructions do not have type information; Gen instructions do.
2531enum Stage1ZirInstId : uint8_t {
2532 Stage1ZirInstIdInvalid,
2533 Stage1ZirInstIdDeclVar,
2534 Stage1ZirInstIdBr,
2535 Stage1ZirInstIdCondBr,
2536 Stage1ZirInstIdSwitchBr,
2537 Stage1ZirInstIdSwitchVar,
2538 Stage1ZirInstIdSwitchElseVar,
2539 Stage1ZirInstIdSwitchTarget,
2540 Stage1ZirInstIdPhi,
2541 Stage1ZirInstIdUnOp,
2542 Stage1ZirInstIdBinOp,
2543 Stage1ZirInstIdMergeErrSets,
2544 Stage1ZirInstIdLoadPtr,
2545 Stage1ZirInstIdStorePtr,
2546 Stage1ZirInstIdFieldPtr,
2547 Stage1ZirInstIdElemPtr,
2548 Stage1ZirInstIdVarPtr,
2549 Stage1ZirInstIdCall,
2550 Stage1ZirInstIdCallArgs,
2551 Stage1ZirInstIdCallExtra,
2552 Stage1ZirInstIdAsyncCallExtra,
2553 Stage1ZirInstIdConst,
2554 Stage1ZirInstIdReturn,
2555 Stage1ZirInstIdContainerInitList,
2556 Stage1ZirInstIdContainerInitFields,
2557 Stage1ZirInstIdUnreachable,
2558 Stage1ZirInstIdTypeOf,
2559 Stage1ZirInstIdSetCold,
2560 Stage1ZirInstIdSetRuntimeSafety,
2561 Stage1ZirInstIdSetFloatMode,
2562 Stage1ZirInstIdArrayType,
2563 Stage1ZirInstIdAnyFrameType,
2564 Stage1ZirInstIdSliceType,
2565 Stage1ZirInstIdAsm,
2566 Stage1ZirInstIdSizeOf,
2567 Stage1ZirInstIdTestNonNull,
2568 Stage1ZirInstIdOptionalUnwrapPtr,
2569 Stage1ZirInstIdClz,
2570 Stage1ZirInstIdCtz,
2571 Stage1ZirInstIdPopCount,
2572 Stage1ZirInstIdBswap,
2573 Stage1ZirInstIdBitReverse,
2574 Stage1ZirInstIdImport,
2575 Stage1ZirInstIdCImport,
2576 Stage1ZirInstIdCInclude,
2577 Stage1ZirInstIdCDefine,
2578 Stage1ZirInstIdCUndef,
2579 Stage1ZirInstIdRef,
2580 Stage1ZirInstIdCompileErr,
2581 Stage1ZirInstIdCompileLog,
2582 Stage1ZirInstIdErrName,
2583 Stage1ZirInstIdEmbedFile,
2584 Stage1ZirInstIdCmpxchg,
2585 Stage1ZirInstIdFence,
2586 Stage1ZirInstIdReduce,
2587 Stage1ZirInstIdTruncate,
2588 Stage1ZirInstIdIntCast,
2589 Stage1ZirInstIdFloatCast,
2590 Stage1ZirInstIdIntToFloat,
2591 Stage1ZirInstIdFloatToInt,
2592 Stage1ZirInstIdBoolToInt,
2593 Stage1ZirInstIdVectorType,
2594 Stage1ZirInstIdShuffleVector,
2595 Stage1ZirInstIdSelect,
2596 Stage1ZirInstIdSplat,
2597 Stage1ZirInstIdBoolNot,
2598 Stage1ZirInstIdMemset,
2599 Stage1ZirInstIdMemcpy,
2600 Stage1ZirInstIdSlice,
2601 Stage1ZirInstIdBreakpoint,
2602 Stage1ZirInstIdReturnAddress,
2603 Stage1ZirInstIdFrameAddress,
2604 Stage1ZirInstIdFrameHandle,
2605 Stage1ZirInstIdFrameType,
2606 Stage1ZirInstIdFrameSize,
2607 Stage1ZirInstIdAlignOf,
2608 Stage1ZirInstIdOverflowOp,
2609 Stage1ZirInstIdTestErr,
2610 Stage1ZirInstIdMulAdd,
2611 Stage1ZirInstIdFloatOp,
2612 Stage1ZirInstIdUnwrapErrCode,
2613 Stage1ZirInstIdUnwrapErrPayload,
2614 Stage1ZirInstIdFnProto,
2615 Stage1ZirInstIdTestComptime,
2616 Stage1ZirInstIdPtrCast,
2617 Stage1ZirInstIdBitCast,
2618 Stage1ZirInstIdIntToPtr,
2619 Stage1ZirInstIdPtrToInt,
2620 Stage1ZirInstIdIntToEnum,
2621 Stage1ZirInstIdEnumToInt,
2622 Stage1ZirInstIdIntToErr,
2623 Stage1ZirInstIdErrToInt,
2624 Stage1ZirInstIdCheckSwitchProngsUnderYes,
2625 Stage1ZirInstIdCheckSwitchProngsUnderNo,
2626 Stage1ZirInstIdCheckStatementIsVoid,
2627 Stage1ZirInstIdTypeName,
2628 Stage1ZirInstIdDeclRef,
2629 Stage1ZirInstIdPanic,
2630 Stage1ZirInstIdTagName,
2631 Stage1ZirInstIdFieldParentPtr,
2632 Stage1ZirInstIdOffsetOf,
2633 Stage1ZirInstIdBitOffsetOf,
2634 Stage1ZirInstIdTypeInfo,
2635 Stage1ZirInstIdType,
2636 Stage1ZirInstIdHasField,
2637 Stage1ZirInstIdSetEvalBranchQuota,
2638 Stage1ZirInstIdPtrType,
2639 Stage1ZirInstIdPtrTypeSimple,
2640 Stage1ZirInstIdPtrTypeSimpleConst,
2641 Stage1ZirInstIdAlignCast,
2642 Stage1ZirInstIdImplicitCast,
2643 Stage1ZirInstIdResolveResult,
2644 Stage1ZirInstIdResetResult,
2645 Stage1ZirInstIdSetAlignStack,
2646 Stage1ZirInstIdArgTypeAllowVarFalse,
2647 Stage1ZirInstIdArgTypeAllowVarTrue,
2648 Stage1ZirInstIdExport,
2649 Stage1ZirInstIdExtern,
2650 Stage1ZirInstIdErrorReturnTrace,
2651 Stage1ZirInstIdErrorUnion,
2652 Stage1ZirInstIdAtomicRmw,
2653 Stage1ZirInstIdAtomicLoad,
2654 Stage1ZirInstIdAtomicStore,
2655 Stage1ZirInstIdSaveErrRetAddr,
2656 Stage1ZirInstIdAddImplicitReturnType,
2657 Stage1ZirInstIdErrSetCast,
2658 Stage1ZirInstIdCheckRuntimeScope,
2659 Stage1ZirInstIdHasDecl,
2660 Stage1ZirInstIdUndeclaredIdent,
2661 Stage1ZirInstIdAlloca,
2662 Stage1ZirInstIdEndExpr,
2663 Stage1ZirInstIdUnionInitNamedField,
2664 Stage1ZirInstIdSuspendBegin,
2665 Stage1ZirInstIdSuspendFinish,
2666 Stage1ZirInstIdAwait,
2667 Stage1ZirInstIdResume,
2668 Stage1ZirInstIdSpillBegin,
2669 Stage1ZirInstIdSpillEnd,
2670 Stage1ZirInstIdWasmMemorySize,
2671 Stage1ZirInstIdWasmMemoryGrow,
2672 Stage1ZirInstIdSrc,
2673 Stage1ZirInstIdPrefetch,
2674 Stage1ZirInstIdAddrSpaceCast,
2675};
2676
2677// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
2678// Src instructions do not have type information; Gen instructions do.
2679enum Stage1AirInstId : uint8_t {
2680 Stage1AirInstIdInvalid,
2681 Stage1AirInstIdDeclVar,
2682 Stage1AirInstIdBr,
2683 Stage1AirInstIdCondBr,
2684 Stage1AirInstIdSwitchBr,
2685 Stage1AirInstIdPhi,
2686 Stage1AirInstIdBinaryNot,
2687 Stage1AirInstIdNegation,
2688 Stage1AirInstIdBinOp,
2689 Stage1AirInstIdLoadPtr,
2690 Stage1AirInstIdStorePtr,
2691 Stage1AirInstIdVectorStoreElem,
2692 Stage1AirInstIdStructFieldPtr,
2693 Stage1AirInstIdUnionFieldPtr,
2694 Stage1AirInstIdElemPtr,
2695 Stage1AirInstIdVarPtr,
2696 Stage1AirInstIdReturnPtr,
2697 Stage1AirInstIdCall,
2698 Stage1AirInstIdReturn,
2699 Stage1AirInstIdCast,
2700 Stage1AirInstIdUnreachable,
2701 Stage1AirInstIdAsm,
2702 Stage1AirInstIdTestNonNull,
2703 Stage1AirInstIdOptionalUnwrapPtr,
2704 Stage1AirInstIdOptionalWrap,
2705 Stage1AirInstIdUnionTag,
2706 Stage1AirInstIdClz,
2707 Stage1AirInstIdCtz,
2708 Stage1AirInstIdPopCount,
2709 Stage1AirInstIdBswap,
2710 Stage1AirInstIdBitReverse,
2711 Stage1AirInstIdRef,
2712 Stage1AirInstIdErrName,
2713 Stage1AirInstIdCmpxchg,
2714 Stage1AirInstIdFence,
2715 Stage1AirInstIdReduce,
2716 Stage1AirInstIdTruncate,
2717 Stage1AirInstIdShuffleVector,
2718 Stage1AirInstIdSelect,
2719 Stage1AirInstIdSplat,
2720 Stage1AirInstIdBoolNot,
2721 Stage1AirInstIdMemset,
2722 Stage1AirInstIdMemcpy,
2723 Stage1AirInstIdSlice,
2724 Stage1AirInstIdBreakpoint,
2725 Stage1AirInstIdReturnAddress,
2726 Stage1AirInstIdFrameAddress,
2727 Stage1AirInstIdFrameHandle,
2728 Stage1AirInstIdFrameSize,
2729 Stage1AirInstIdOverflowOp,
2730 Stage1AirInstIdTestErr,
2731 Stage1AirInstIdMulAdd,
2732 Stage1AirInstIdFloatOp,
2733 Stage1AirInstIdUnwrapErrCode,
2734 Stage1AirInstIdUnwrapErrPayload,
2735 Stage1AirInstIdErrWrapCode,
2736 Stage1AirInstIdErrWrapPayload,
2737 Stage1AirInstIdPtrCast,
2738 Stage1AirInstIdBitCast,
2739 Stage1AirInstIdWidenOrShorten,
2740 Stage1AirInstIdIntToPtr,
2741 Stage1AirInstIdPtrToInt,
2742 Stage1AirInstIdIntToEnum,
2743 Stage1AirInstIdIntToErr,
2744 Stage1AirInstIdErrToInt,
2745 Stage1AirInstIdPanic,
2746 Stage1AirInstIdTagName,
2747 Stage1AirInstIdFieldParentPtr,
2748 Stage1AirInstIdAlignCast,
2749 Stage1AirInstIdErrorReturnTrace,
2750 Stage1AirInstIdAtomicRmw,
2751 Stage1AirInstIdAtomicLoad,
2752 Stage1AirInstIdAtomicStore,
2753 Stage1AirInstIdSaveErrRetAddr,
2754 Stage1AirInstIdVectorToArray,
2755 Stage1AirInstIdArrayToVector,
2756 Stage1AirInstIdAssertZero,
2757 Stage1AirInstIdAssertNonNull,
2758 Stage1AirInstIdPtrOfArrayToSlice,
2759 Stage1AirInstIdSuspendBegin,
2760 Stage1AirInstIdSuspendFinish,
2761 Stage1AirInstIdAwait,
2762 Stage1AirInstIdResume,
2763 Stage1AirInstIdSpillBegin,
2764 Stage1AirInstIdSpillEnd,
2765 Stage1AirInstIdVectorExtractElem,
2766 Stage1AirInstIdAlloca,
2767 Stage1AirInstIdConst,
2768 Stage1AirInstIdWasmMemorySize,
2769 Stage1AirInstIdWasmMemoryGrow,
2770 Stage1AirInstIdExtern,
2771 Stage1AirInstIdPrefetch,
2772};
2773
2774struct Stage1ZirInst {
2775 Stage1ZirInstId id;
2776 uint16_t ref_count;
2777 uint32_t debug_id;
2778
2779 Scope *scope;
2780 AstNode *source_node;
2781
2782 // When analyzing IR, instructions that point to this instruction in the "old ir"
2783 // can find the instruction that corresponds to this value in the "new ir"
2784 // with this child field.
2785 Stage1AirInst *child;
2786 Stage1ZirBasicBlock *owner_bb;
2787
2788 // for debugging purposes, these are useful to call to inspect the instruction
2789 void dump();
2790 void src();
2791};
2792
2793struct Stage1AirInst {
2794 Stage1AirInstId id;
2795 // if ref_count is zero and the instruction has no side effects,
2796 // the instruction can be omitted in codegen
2797 uint16_t ref_count;
2798 uint32_t debug_id;
2799
2800 Scope *scope;
2801 AstNode *source_node;
2802
2803 LLVMValueRef llvm_value;
2804 ZigValue *value;
2805 // Nearly any instruction can have to be stored as a local variable before suspending
2806 // and then loaded after resuming, in case there is an expression with a suspend point
2807 // in it, such as: x + await y
2808 Stage1AirInst *spill;
2809
2810 // for debugging purposes, these are useful to call to inspect the instruction
2811 void dump();
2812 void src();
2813};
2814
2815struct Stage1ZirInstDeclVar {
2816 Stage1ZirInst base;
2817
2818 ZigVar *var;
2819 Stage1ZirInst *var_type;
2820 Stage1ZirInst *align_value;
2821 Stage1ZirInst *ptr;
2822};
2823
2824struct Stage1AirInstDeclVar {
2825 Stage1AirInst base;
2826
2827 ZigVar *var;
2828 Stage1AirInst *var_ptr;
2829};
2830
2831struct Stage1ZirInstCondBr {
2832 Stage1ZirInst base;
2833
2834 Stage1ZirInst *condition;
2835 Stage1ZirBasicBlock *then_block;
2836 Stage1ZirBasicBlock *else_block;
2837 Stage1ZirInst *is_comptime;
2838 ResultLoc *result_loc;
2839};
2840
2841struct Stage1AirInstCondBr {
2842 Stage1AirInst base;
2843
2844 Stage1AirInst *condition;
2845 Stage1AirBasicBlock *then_block;
2846 Stage1AirBasicBlock *else_block;
2847};
2848
2849struct Stage1ZirInstBr {
2850 Stage1ZirInst base;
2851
2852 Stage1ZirBasicBlock *dest_block;
2853 Stage1ZirInst *is_comptime;
2854};
2855
2856struct Stage1AirInstBr {
2857 Stage1AirInst base;
2858
2859 Stage1AirBasicBlock *dest_block;
2860};
2861
2862struct Stage1ZirInstSwitchBrCase {
2863 Stage1ZirInst *value;
2864 Stage1ZirBasicBlock *block;
2865};
2866
2867struct Stage1ZirInstSwitchBr {
2868 Stage1ZirInst base;
2869
2870 Stage1ZirInst *target_value;
2871 Stage1ZirBasicBlock *else_block;
2872 size_t case_count;
2873 Stage1ZirInstSwitchBrCase *cases;
2874 Stage1ZirInst *is_comptime;
2875 Stage1ZirInst *switch_prongs_void;
2876};
2877
2878struct Stage1AirInstSwitchBrCase {
2879 Stage1AirInst *value;
2880 Stage1AirBasicBlock *block;
2881};
2882
2883struct Stage1AirInstSwitchBr {
2884 Stage1AirInst base;
2885
2886 Stage1AirInst *target_value;
2887 Stage1AirBasicBlock *else_block;
2888 size_t case_count;
2889 Stage1AirInstSwitchBrCase *cases;
2890};
2891
2892struct Stage1ZirInstSwitchVar {
2893 Stage1ZirInst base;
2894
2895 Stage1ZirInst *target_value_ptr;
2896 Stage1ZirInst **prongs_ptr;
2897 size_t prongs_len;
2898};
2899
2900struct Stage1ZirInstSwitchElseVar {
2901 Stage1ZirInst base;
2902
2903 Stage1ZirInst *target_value_ptr;
2904 Stage1ZirInstSwitchBr *switch_br;
2905};
2906
2907struct Stage1ZirInstSwitchTarget {
2908 Stage1ZirInst base;
2909
2910 Stage1ZirInst *target_value_ptr;
2911};
2912
2913struct Stage1ZirInstPhi {
2914 Stage1ZirInst base;
2915
2916 size_t incoming_count;
2917 bool merge_comptime;
2918 Stage1ZirBasicBlock **incoming_blocks;
2919 Stage1ZirInst **incoming_values;
2920 ResultLocPeerParent *peer_parent;
2921};
2922
2923struct Stage1AirInstPhi {
2924 Stage1AirInst base;
2925
2926 size_t incoming_count;
2927 Stage1AirBasicBlock **incoming_blocks;
2928 Stage1AirInst **incoming_values;
2929};
2930
2931enum IrUnOp {
2932 IrUnOpInvalid,
2933 IrUnOpBinNot,
2934 IrUnOpNegation,
2935 IrUnOpNegationWrap,
2936 IrUnOpDereference,
2937 IrUnOpOptional,
2938};
2939
2940struct Stage1ZirInstUnOp {
2941 Stage1ZirInst base;
2942
2943 IrUnOp op_id;
2944 LVal lval;
2945 Stage1ZirInst *value;
2946 ResultLoc *result_loc;
2947};
2948
2949struct Stage1AirInstBinaryNot {
2950 Stage1AirInst base;
2951 Stage1AirInst *operand;
2952};
2953
2954struct Stage1AirInstNegation {
2955 Stage1AirInst base;
2956 Stage1AirInst *operand;
2957 bool wrapping;
2958};
2959
2960enum IrBinOp {
2961 IrBinOpInvalid,
2962 IrBinOpBoolOr,
2963 IrBinOpBoolAnd,
2964 IrBinOpCmpEq,
2965 IrBinOpCmpNotEq,
2966 IrBinOpCmpLessThan,
2967 IrBinOpCmpGreaterThan,
2968 IrBinOpCmpLessOrEq,
2969 IrBinOpCmpGreaterOrEq,
2970 IrBinOpBinOr,
2971 IrBinOpBinXor,
2972 IrBinOpBinAnd,
2973 IrBinOpBitShiftLeftLossy,
2974 IrBinOpBitShiftLeftExact,
2975 IrBinOpBitShiftRightLossy,
2976 IrBinOpBitShiftRightExact,
2977 IrBinOpAdd,
2978 IrBinOpAddWrap,
2979 IrBinOpSub,
2980 IrBinOpSubWrap,
2981 IrBinOpMult,
2982 IrBinOpMultWrap,
2983 IrBinOpDivUnspecified,
2984 IrBinOpDivExact,
2985 IrBinOpDivTrunc,
2986 IrBinOpDivFloor,
2987 IrBinOpRemUnspecified,
2988 IrBinOpRemRem,
2989 IrBinOpRemMod,
2990 IrBinOpArrayCat,
2991 IrBinOpArrayMult,
2992 IrBinOpMax,
2993 IrBinOpMin,
2994 IrBinOpAddSat,
2995 IrBinOpSubSat,
2996 IrBinOpMultSat,
2997 IrBinOpShlSat,
2998};
2999
3000struct Stage1ZirInstBinOp {
3001 Stage1ZirInst base;
3002
3003 Stage1ZirInst *op1;
3004 Stage1ZirInst *op2;
3005 IrBinOp op_id;
3006 bool safety_check_on;
3007};
3008
3009struct Stage1AirInstBinOp {
3010 Stage1AirInst base;
3011
3012 Stage1AirInst *op1;
3013 Stage1AirInst *op2;
3014 IrBinOp op_id;
3015 bool safety_check_on;
3016};
3017
3018struct Stage1ZirInstMergeErrSets {
3019 Stage1ZirInst base;
3020
3021 Stage1ZirInst *op1;
3022 Stage1ZirInst *op2;
3023 Buf *type_name;
3024};
3025
3026struct Stage1ZirInstLoadPtr {
3027 Stage1ZirInst base;
3028
3029 Stage1ZirInst *ptr;
3030};
3031
3032struct Stage1AirInstLoadPtr {
3033 Stage1AirInst base;
3034
3035 Stage1AirInst *ptr;
3036 Stage1AirInst *result_loc;
3037};
3038
3039struct Stage1ZirInstStorePtr {
3040 Stage1ZirInst base;
3041
3042 Stage1ZirInst *ptr;
3043 Stage1ZirInst *value;
3044
3045 bool allow_write_through_const;
3046};
3047
3048struct Stage1AirInstStorePtr {
3049 Stage1AirInst base;
3050
3051 Stage1AirInst *ptr;
3052 Stage1AirInst *value;
3053};
3054
3055struct Stage1AirInstVectorStoreElem {
3056 Stage1AirInst base;
3057
3058 Stage1AirInst *vector_ptr;
3059 Stage1AirInst *index;
3060 Stage1AirInst *value;
3061};
3062
3063struct Stage1ZirInstFieldPtr {
3064 Stage1ZirInst base;
3065
3066 Stage1ZirInst *container_ptr;
3067 Buf *field_name_buffer;
3068 Stage1ZirInst *field_name_expr;
3069 bool initializing;
3070};
3071
3072struct Stage1AirInstStructFieldPtr {
3073 Stage1AirInst base;
3074
3075 Stage1AirInst *struct_ptr;
3076 TypeStructField *field;
3077 bool is_const;
3078};
3079
3080struct Stage1AirInstUnionFieldPtr {
3081 Stage1AirInst base;
3082
3083 Stage1AirInst *union_ptr;
3084 TypeUnionField *field;
3085 bool safety_check_on;
3086 bool initializing;
3087};
3088
3089struct Stage1ZirInstElemPtr {
3090 Stage1ZirInst base;
3091
3092 Stage1ZirInst *array_ptr;
3093 Stage1ZirInst *elem_index;
3094 AstNode *init_array_type_source_node;
3095 PtrLen ptr_len;
3096 bool safety_check_on;
3097};
3098
3099struct Stage1AirInstElemPtr {
3100 Stage1AirInst base;
3101
3102 Stage1AirInst *array_ptr;
3103 Stage1AirInst *elem_index;
3104 bool safety_check_on;
3105};
3106
3107struct Stage1ZirInstVarPtr {
3108 Stage1ZirInst base;
3109
3110 ZigVar *var;
3111 ScopeFnDef *crossed_fndef_scope;
3112};
3113
3114struct Stage1AirInstVarPtr {
3115 Stage1AirInst base;
3116
3117 ZigVar *var;
3118};
3119
3120// For functions that have a return type for which handle_is_ptr is true, a
3121// result location pointer is the secret first parameter ("sret"). This
3122// instruction returns that pointer.
3123struct Stage1AirInstReturnPtr {
3124 Stage1AirInst base;
3125};
3126
3127struct Stage1ZirInstCall {
3128 Stage1ZirInst base;
3129
3130 Stage1ZirInst *fn_ref;
3131 ZigFn *fn_entry;
3132 size_t arg_count;
3133 Stage1ZirInst **args;
3134 Stage1ZirInst *ret_ptr;
3135 ResultLoc *result_loc;
3136
3137 Stage1ZirInst *new_stack;
3138
3139 CallModifier modifier;
3140 bool is_async_call_builtin;
3141};
3142
3143// This is a pass1 instruction, used by @call when the args node is
3144// a tuple or struct literal.
3145struct Stage1ZirInstCallArgs {
3146 Stage1ZirInst base;
3147
3148 Stage1ZirInst *options;
3149 Stage1ZirInst *fn_ref;
3150 Stage1ZirInst **args_ptr;
3151 size_t args_len;
3152 ResultLoc *result_loc;
3153};
3154
3155// This is a pass1 instruction, used by @call, when the args node
3156// is not a literal.
3157// `args` is expected to be either a struct or a tuple.
3158struct Stage1ZirInstCallExtra {
3159 Stage1ZirInst base;
3160
3161 Stage1ZirInst *options;
3162 Stage1ZirInst *fn_ref;
3163 Stage1ZirInst *args;
3164 ResultLoc *result_loc;
3165};
3166
3167// This is a pass1 instruction, used by @asyncCall, when the args node
3168// is not a literal.
3169// `args` is expected to be either a struct or a tuple.
3170struct Stage1ZirInstAsyncCallExtra {
3171 Stage1ZirInst base;
3172
3173 CallModifier modifier;
3174 Stage1ZirInst *fn_ref;
3175 Stage1ZirInst *ret_ptr;
3176 Stage1ZirInst *new_stack;
3177 Stage1ZirInst *args;
3178 ResultLoc *result_loc;
3179};
3180
3181struct Stage1AirInstCall {
3182 Stage1AirInst base;
3183
3184 Stage1AirInst *fn_ref;
3185 ZigFn *fn_entry;
3186 size_t arg_count;
3187 Stage1AirInst **args;
3188 Stage1AirInst *result_loc;
3189 Stage1AirInst *frame_result_loc;
3190 Stage1AirInst *new_stack;
3191
3192 CallModifier modifier;
3193
3194 bool is_async_call_builtin;
3195};
3196
3197struct Stage1ZirInstConst {
3198 Stage1ZirInst base;
3199
3200 ZigValue *value;
3201};
3202
3203struct Stage1AirInstConst {
3204 Stage1AirInst base;
3205};
3206
3207struct Stage1ZirInstReturn {
3208 Stage1ZirInst base;
3209
3210 Stage1ZirInst *operand;
3211};
3212
3213// When an IrExecutable is not in a function, a return instruction means that
3214// the expression returns with that value, even though a return statement from
3215// an AST perspective is invalid.
3216struct Stage1AirInstReturn {
3217 Stage1AirInst base;
3218
3219 Stage1AirInst *operand;
3220};
3221
3222enum CastOp {
3223 CastOpNoCast, // signifies the function call expression is not a cast
3224 CastOpNoop, // fn call expr is a cast, but does nothing
3225 CastOpIntToFloat,
3226 CastOpFloatToInt,
3227 CastOpBoolToInt,
3228 CastOpNumLitToConcrete,
3229 CastOpErrSet,
3230 CastOpBitCast,
3231};
3232
3233// TODO get rid of this instruction, replace with instructions for each op code
3234struct Stage1AirInstCast {
3235 Stage1AirInst base;
3236
3237 Stage1AirInst *value;
3238 CastOp cast_op;
3239};
3240
3241struct Stage1ZirInstContainerInitList {
3242 Stage1ZirInst base;
3243
3244 Stage1ZirInst *elem_type;
3245 size_t item_count;
3246 Stage1ZirInst **elem_result_loc_list;
3247 Stage1ZirInst *result_loc;
3248 AstNode *init_array_type_source_node;
3249};
3250
3251struct Stage1ZirInstContainerInitFieldsField {
3252 Buf *name;
3253 AstNode *source_node;
3254 Stage1ZirInst *result_loc;
3255};
3256
3257struct Stage1ZirInstContainerInitFields {
3258 Stage1ZirInst base;
3259
3260 size_t field_count;
3261 Stage1ZirInstContainerInitFieldsField *fields;
3262 Stage1ZirInst *result_loc;
3263};
3264
3265struct Stage1ZirInstUnreachable {
3266 Stage1ZirInst base;
3267};
3268
3269struct Stage1AirInstUnreachable {
3270 Stage1AirInst base;
3271};
3272
3273struct Stage1ZirInstTypeOf {
3274 Stage1ZirInst base;
3275
3276 union {
3277 Stage1ZirInst *scalar; // value_count == 1
3278 Stage1ZirInst **list; // value_count > 1
3279 } value;
3280 size_t value_count;
3281};
3282
3283struct Stage1ZirInstSetCold {
3284 Stage1ZirInst base;
3285
3286 Stage1ZirInst *is_cold;
3287};
3288
3289struct Stage1ZirInstSetRuntimeSafety {
3290 Stage1ZirInst base;
3291
3292 Stage1ZirInst *safety_on;
3293};
3294
3295struct Stage1ZirInstSetFloatMode {
3296 Stage1ZirInst base;
3297
3298 Stage1ZirInst *scope_value;
3299 Stage1ZirInst *mode_value;
3300};
3301
3302struct Stage1ZirInstArrayType {
3303 Stage1ZirInst base;
3304
3305 Stage1ZirInst *size;
3306 Stage1ZirInst *sentinel;
3307 Stage1ZirInst *child_type;
3308};
3309
3310struct Stage1ZirInstPtrTypeSimple {
3311 Stage1ZirInst base;
3312
3313 Stage1ZirInst *child_type;
3314};
3315
3316struct Stage1ZirInstPtrType {
3317 Stage1ZirInst base;
3318
3319 Stage1ZirInst *sentinel;
3320 Stage1ZirInst *align_value;
3321 Stage1ZirInst *child_type;
3322 uint32_t bit_offset_start;
3323 uint32_t host_int_bytes;
3324 PtrLen ptr_len;
3325 bool is_const;
3326 bool is_volatile;
3327 bool is_allow_zero;
3328};
3329
3330struct Stage1ZirInstAnyFrameType {
3331 Stage1ZirInst base;
3332
3333 Stage1ZirInst *payload_type;
3334};
3335
3336struct Stage1ZirInstSliceType {
3337 Stage1ZirInst base;
3338
3339 Stage1ZirInst *sentinel;
3340 Stage1ZirInst *align_value;
3341 Stage1ZirInst *child_type;
3342 bool is_const;
3343 bool is_volatile;
3344 bool is_allow_zero;
3345};
3346
3347struct Stage1ZirInstAsm {
3348 Stage1ZirInst base;
3349
3350 Stage1ZirInst *asm_template;
3351 Stage1ZirInst **input_list;
3352 Stage1ZirInst **output_types;
3353 ZigVar **output_vars;
3354 size_t return_count;
3355 bool has_side_effects;
3356 bool is_global;
3357};
3358
3359struct Stage1AirInstAsm {
3360 Stage1AirInst base;
3361
3362 Buf *asm_template;
3363 AsmToken *token_list;
3364 size_t token_list_len;
3365 Stage1AirInst **input_list;
3366 Stage1AirInst **output_types;
3367 ZigVar **output_vars;
3368 size_t return_count;
3369 bool has_side_effects;
3370};
3371
3372struct Stage1ZirInstSizeOf {
3373 Stage1ZirInst base;
3374
3375 Stage1ZirInst *type_value;
3376 bool bit_size;
3377};
3378
3379// returns true if nonnull, returns false if null
3380struct Stage1ZirInstTestNonNull {
3381 Stage1ZirInst base;
3382
3383 Stage1ZirInst *value;
3384};
3385
3386struct Stage1AirInstTestNonNull {
3387 Stage1AirInst base;
3388
3389 Stage1AirInst *value;
3390};
3391
3392// Takes a pointer to an optional value, returns a pointer
3393// to the payload.
3394struct Stage1ZirInstOptionalUnwrapPtr {
3395 Stage1ZirInst base;
3396
3397 Stage1ZirInst *base_ptr;
3398 bool safety_check_on;
3399};
3400
3401struct Stage1AirInstOptionalUnwrapPtr {
3402 Stage1AirInst base;
3403
3404 Stage1AirInst *base_ptr;
3405 bool safety_check_on;
3406 bool initializing;
3407};
3408
3409struct Stage1ZirInstCtz {
3410 Stage1ZirInst base;
3411
3412 Stage1ZirInst *type;
3413 Stage1ZirInst *op;
3414};
3415
3416struct Stage1AirInstCtz {
3417 Stage1AirInst base;
3418
3419 Stage1AirInst *op;
3420};
3421
3422struct Stage1ZirInstClz {
3423 Stage1ZirInst base;
3424
3425 Stage1ZirInst *type;
3426 Stage1ZirInst *op;
3427};
3428
3429struct Stage1AirInstClz {
3430 Stage1AirInst base;
3431
3432 Stage1AirInst *op;
3433};
3434
3435struct Stage1ZirInstPopCount {
3436 Stage1ZirInst base;
3437
3438 Stage1ZirInst *type;
3439 Stage1ZirInst *op;
3440};
3441
3442struct Stage1AirInstPopCount {
3443 Stage1AirInst base;
3444
3445 Stage1AirInst *op;
3446};
3447
3448struct Stage1AirInstUnionTag {
3449 Stage1AirInst base;
3450
3451 Stage1AirInst *value;
3452};
3453
3454struct Stage1ZirInstImport {
3455 Stage1ZirInst base;
3456
3457 Stage1ZirInst *name;
3458};
3459
3460struct Stage1ZirInstRef {
3461 Stage1ZirInst base;
3462
3463 Stage1ZirInst *value;
3464};
3465
3466struct Stage1AirInstRef {
3467 Stage1AirInst base;
3468
3469 Stage1AirInst *operand;
3470 Stage1AirInst *result_loc;
3471};
3472
3473struct Stage1ZirInstCompileErr {
3474 Stage1ZirInst base;
3475
3476 Stage1ZirInst *msg;
3477};
3478
3479struct Stage1ZirInstCompileLog {
3480 Stage1ZirInst base;
3481
3482 size_t msg_count;
3483 Stage1ZirInst **msg_list;
3484};
3485
3486struct Stage1ZirInstErrName {
3487 Stage1ZirInst base;
3488
3489 Stage1ZirInst *value;
3490};
3491
3492struct Stage1AirInstErrName {
3493 Stage1AirInst base;
3494
3495 Stage1AirInst *value;
3496};
3497
3498struct Stage1ZirInstCImport {
3499 Stage1ZirInst base;
3500};
3501
3502struct Stage1ZirInstCInclude {
3503 Stage1ZirInst base;
3504
3505 Stage1ZirInst *name;
3506};
3507
3508struct Stage1ZirInstCDefine {
3509 Stage1ZirInst base;
3510
3511 Stage1ZirInst *name;
3512 Stage1ZirInst *value;
3513};
3514
3515struct Stage1ZirInstCUndef {
3516 Stage1ZirInst base;
3517
3518 Stage1ZirInst *name;
3519};
3520
3521struct Stage1ZirInstEmbedFile {
3522 Stage1ZirInst base;
3523
3524 Stage1ZirInst *name;
3525};
3526
3527struct Stage1ZirInstCmpxchg {
3528 Stage1ZirInst base;
3529
3530 bool is_weak;
3531 Stage1ZirInst *type_value;
3532 Stage1ZirInst *ptr;
3533 Stage1ZirInst *cmp_value;
3534 Stage1ZirInst *new_value;
3535 Stage1ZirInst *success_order_value;
3536 Stage1ZirInst *failure_order_value;
3537 ResultLoc *result_loc;
3538};
3539
3540struct Stage1AirInstCmpxchg {
3541 Stage1AirInst base;
3542
3543 AtomicOrder success_order;
3544 AtomicOrder failure_order;
3545 Stage1AirInst *ptr;
3546 Stage1AirInst *cmp_value;
3547 Stage1AirInst *new_value;
3548 Stage1AirInst *result_loc;
3549 bool is_weak;
3550};
3551
3552struct Stage1ZirInstFence {
3553 Stage1ZirInst base;
3554
3555 Stage1ZirInst *order;
3556};
3557
3558struct Stage1AirInstFence {
3559 Stage1AirInst base;
3560
3561 AtomicOrder order;
3562};
3563
3564struct Stage1ZirInstReduce {
3565 Stage1ZirInst base;
3566
3567 Stage1ZirInst *op;
3568 Stage1ZirInst *value;
3569};
3570
3571struct Stage1AirInstReduce {
3572 Stage1AirInst base;
3573
3574 ReduceOp op;
3575 Stage1AirInst *value;
3576};
3577
3578struct Stage1ZirInstTruncate {
3579 Stage1ZirInst base;
3580
3581 Stage1ZirInst *dest_type;
3582 Stage1ZirInst *target;
3583};
3584
3585struct Stage1AirInstTruncate {
3586 Stage1AirInst base;
3587
3588 Stage1AirInst *target;
3589};
3590
3591struct Stage1ZirInstIntCast {
3592 Stage1ZirInst base;
3593
3594 Stage1ZirInst *dest_type;
3595 Stage1ZirInst *target;
3596};
3597
3598struct Stage1ZirInstFloatCast {
3599 Stage1ZirInst base;
3600
3601 Stage1ZirInst *dest_type;
3602 Stage1ZirInst *target;
3603};
3604
3605struct Stage1ZirInstErrSetCast {
3606 Stage1ZirInst base;
3607
3608 Stage1ZirInst *dest_type;
3609 Stage1ZirInst *target;
3610};
3611
3612struct Stage1ZirInstIntToFloat {
3613 Stage1ZirInst base;
3614
3615 Stage1ZirInst *dest_type;
3616 Stage1ZirInst *target;
3617};
3618
3619struct Stage1ZirInstFloatToInt {
3620 Stage1ZirInst base;
3621
3622 Stage1ZirInst *dest_type;
3623 Stage1ZirInst *target;
3624};
3625
3626struct Stage1ZirInstBoolToInt {
3627 Stage1ZirInst base;
3628
3629 Stage1ZirInst *target;
3630};
3631
3632struct Stage1ZirInstVectorType {
3633 Stage1ZirInst base;
3634
3635 Stage1ZirInst *len;
3636 Stage1ZirInst *elem_type;
3637};
3638
3639struct Stage1ZirInstBoolNot {
3640 Stage1ZirInst base;
3641
3642 Stage1ZirInst *value;
3643};
3644
3645struct Stage1AirInstBoolNot {
3646 Stage1AirInst base;
3647
3648 Stage1AirInst *value;
3649};
3650
3651struct Stage1ZirInstMemset {
3652 Stage1ZirInst base;
3653
3654 Stage1ZirInst *dest_ptr;
3655 Stage1ZirInst *byte;
3656 Stage1ZirInst *count;
3657};
3658
3659struct Stage1AirInstMemset {
3660 Stage1AirInst base;
3661
3662 Stage1AirInst *dest_ptr;
3663 Stage1AirInst *byte;
3664 Stage1AirInst *count;
3665};
3666
3667struct Stage1ZirInstMemcpy {
3668 Stage1ZirInst base;
3669
3670 Stage1ZirInst *dest_ptr;
3671 Stage1ZirInst *src_ptr;
3672 Stage1ZirInst *count;
3673};
3674
3675struct Stage1AirInstMemcpy {
3676 Stage1AirInst base;
3677
3678 Stage1AirInst *dest_ptr;
3679 Stage1AirInst *src_ptr;
3680 Stage1AirInst *count;
3681};
3682
3683struct Stage1ZirInstWasmMemorySize {
3684 Stage1ZirInst base;
3685
3686 Stage1ZirInst *index;
3687};
3688
3689struct Stage1AirInstWasmMemorySize {
3690 Stage1AirInst base;
3691
3692 Stage1AirInst *index;
3693};
3694
3695struct Stage1ZirInstWasmMemoryGrow {
3696 Stage1ZirInst base;
3697
3698 Stage1ZirInst *index;
3699 Stage1ZirInst *delta;
3700};
3701
3702struct Stage1AirInstWasmMemoryGrow {
3703 Stage1AirInst base;
3704
3705 Stage1AirInst *index;
3706 Stage1AirInst *delta;
3707};
3708
3709struct Stage1ZirInstSrc {
3710 Stage1ZirInst base;
3711};
3712
3713struct Stage1ZirInstPrefetch {
3714 Stage1ZirInst base;
3715
3716 Stage1ZirInst *ptr;
3717 Stage1ZirInst *options;
3718};
3719
3720struct Stage1AirInstPrefetch {
3721 Stage1AirInst base;
3722
3723 Stage1AirInst *ptr;
3724 PrefetchRw rw;
3725 // Must be in the range 0-3 inclusive
3726 uint8_t locality;
3727 PrefetchCache cache;
3728};
3729
3730
3731struct Stage1ZirInstSlice {
3732 Stage1ZirInst base;
3733
3734 Stage1ZirInst *ptr;
3735 Stage1ZirInst *start;
3736 Stage1ZirInst *end;
3737 Stage1ZirInst *sentinel;
3738 ResultLoc *result_loc;
3739 bool safety_check_on;
3740};
3741
3742struct Stage1AirInstSlice {
3743 Stage1AirInst base;
3744
3745 Stage1AirInst *ptr;
3746 Stage1AirInst *start;
3747 Stage1AirInst *end;
3748 Stage1AirInst *result_loc;
3749 ZigValue *sentinel;
3750 bool safety_check_on;
3751};
3752
3753struct Stage1ZirInstBreakpoint {
3754 Stage1ZirInst base;
3755};
3756
3757struct Stage1AirInstBreakpoint {
3758 Stage1AirInst base;
3759};
3760
3761struct Stage1ZirInstReturnAddress {
3762 Stage1ZirInst base;
3763};
3764
3765struct Stage1AirInstReturnAddress {
3766 Stage1AirInst base;
3767};
3768
3769struct Stage1ZirInstFrameAddress {
3770 Stage1ZirInst base;
3771};
3772
3773struct Stage1AirInstFrameAddress {
3774 Stage1AirInst base;
3775};
3776
3777struct Stage1ZirInstFrameHandle {
3778 Stage1ZirInst base;
3779};
3780
3781struct Stage1AirInstFrameHandle {
3782 Stage1AirInst base;
3783};
3784
3785struct Stage1ZirInstFrameType {
3786 Stage1ZirInst base;
3787
3788 Stage1ZirInst *fn;
3789};
3790
3791struct Stage1ZirInstFrameSize {
3792 Stage1ZirInst base;
3793
3794 Stage1ZirInst *fn;
3795};
3796
3797struct Stage1AirInstFrameSize {
3798 Stage1AirInst base;
3799
3800 Stage1AirInst *fn;
3801};
3802
3803enum IrOverflowOp {
3804 IrOverflowOpAdd,
3805 IrOverflowOpSub,
3806 IrOverflowOpMul,
3807 IrOverflowOpShl,
3808};
3809
3810struct Stage1ZirInstOverflowOp {
3811 Stage1ZirInst base;
3812
3813 IrOverflowOp op;
3814 Stage1ZirInst *type_value;
3815 Stage1ZirInst *op1;
3816 Stage1ZirInst *op2;
3817 Stage1ZirInst *result_ptr;
3818};
3819
3820struct Stage1AirInstOverflowOp {
3821 Stage1AirInst base;
3822
3823 IrOverflowOp op;
3824 Stage1AirInst *op1;
3825 Stage1AirInst *op2;
3826 Stage1AirInst *result_ptr;
3827
3828 // TODO can this field be removed?
3829 ZigType *result_ptr_type;
3830};
3831
3832struct Stage1ZirInstMulAdd {
3833 Stage1ZirInst base;
3834
3835 Stage1ZirInst *type_value;
3836 Stage1ZirInst *op1;
3837 Stage1ZirInst *op2;
3838 Stage1ZirInst *op3;
3839};
3840
3841struct Stage1AirInstMulAdd {
3842 Stage1AirInst base;
3843
3844 Stage1AirInst *op1;
3845 Stage1AirInst *op2;
3846 Stage1AirInst *op3;
3847};
3848
3849struct Stage1ZirInstAlignOf {
3850 Stage1ZirInst base;
3851
3852 Stage1ZirInst *type_value;
3853};
3854
3855// returns true if error, returns false if not error
3856struct Stage1ZirInstTestErr {
3857 Stage1ZirInst base;
3858
3859 Stage1ZirInst *base_ptr;
3860 bool resolve_err_set;
3861 bool base_ptr_is_payload;
3862};
3863
3864struct Stage1AirInstTestErr {
3865 Stage1AirInst base;
3866
3867 Stage1AirInst *err_union;
3868};
3869
3870// Takes an error union pointer, returns a pointer to the error code.
3871struct Stage1ZirInstUnwrapErrCode {
3872 Stage1ZirInst base;
3873
3874 Stage1ZirInst *err_union_ptr;
3875 bool initializing;
3876};
3877
3878struct Stage1AirInstUnwrapErrCode {
3879 Stage1AirInst base;
3880
3881 Stage1AirInst *err_union_ptr;
3882 bool initializing;
3883};
3884
3885struct Stage1ZirInstUnwrapErrPayload {
3886 Stage1ZirInst base;
3887
3888 Stage1ZirInst *value;
3889 bool safety_check_on;
3890 bool initializing;
3891};
3892
3893struct Stage1AirInstUnwrapErrPayload {
3894 Stage1AirInst base;
3895
3896 Stage1AirInst *value;
3897 bool safety_check_on;
3898 bool initializing;
3899};
3900
3901struct Stage1AirInstOptionalWrap {
3902 Stage1AirInst base;
3903
3904 Stage1AirInst *operand;
3905 Stage1AirInst *result_loc;
3906};
3907
3908struct Stage1AirInstErrWrapPayload {
3909 Stage1AirInst base;
3910
3911 Stage1AirInst *operand;
3912 Stage1AirInst *result_loc;
3913};
3914
3915struct Stage1AirInstErrWrapCode {
3916 Stage1AirInst base;
3917
3918 Stage1AirInst *operand;
3919 Stage1AirInst *result_loc;
3920};
3921
3922struct Stage1ZirInstFnProto {
3923 Stage1ZirInst base;
3924
3925 Stage1ZirInst **param_types;
3926 Stage1ZirInst *align_value;
3927 Stage1ZirInst *callconv_value;
3928 Stage1ZirInst *return_type;
3929 bool is_var_args;
3930};
3931
3932// true if the target value is compile time known, false otherwise
3933struct Stage1ZirInstTestComptime {
3934 Stage1ZirInst base;
3935
3936 Stage1ZirInst *value;
3937};
3938
3939struct Stage1ZirInstPtrCast {
3940 Stage1ZirInst base;
3941
3942 Stage1ZirInst *dest_type;
3943 Stage1ZirInst *ptr;
3944 bool safety_check_on;
3945};
3946
3947struct Stage1AirInstPtrCast {
3948 Stage1AirInst base;
3949
3950 Stage1AirInst *ptr;
3951 bool safety_check_on;
3952};
3953
3954struct Stage1ZirInstImplicitCast {
3955 Stage1ZirInst base;
3956
3957 Stage1ZirInst *operand;
3958 ResultLocCast *result_loc_cast;
3959};
3960
3961struct Stage1ZirInstBitCast {
3962 Stage1ZirInst base;
3963
3964 Stage1ZirInst *operand;
3965 ResultLocBitCast *result_loc_bit_cast;
3966};
3967
3968struct Stage1AirInstBitCast {
3969 Stage1AirInst base;
3970
3971 Stage1AirInst *operand;
3972};
3973
3974struct Stage1AirInstWidenOrShorten {
3975 Stage1AirInst base;
3976
3977 Stage1AirInst *target;
3978};
3979
3980struct Stage1ZirInstPtrToInt {
3981 Stage1ZirInst base;
3982
3983 Stage1ZirInst *target;
3984};
3985
3986struct Stage1AirInstPtrToInt {
3987 Stage1AirInst base;
3988
3989 Stage1AirInst *target;
3990};
3991
3992struct Stage1ZirInstIntToPtr {
3993 Stage1ZirInst base;
3994
3995 Stage1ZirInst *dest_type;
3996 Stage1ZirInst *target;
3997};
3998
3999struct Stage1AirInstIntToPtr {
4000 Stage1AirInst base;
4001
4002 Stage1AirInst *target;
4003};
4004
4005struct Stage1ZirInstIntToEnum {
4006 Stage1ZirInst base;
4007
4008 Stage1ZirInst *dest_type;
4009 Stage1ZirInst *target;
4010};
4011
4012struct Stage1AirInstIntToEnum {
4013 Stage1AirInst base;
4014
4015 Stage1AirInst *target;
4016};
4017
4018struct Stage1ZirInstEnumToInt {
4019 Stage1ZirInst base;
4020
4021 Stage1ZirInst *target;
4022};
4023
4024struct Stage1ZirInstIntToErr {
4025 Stage1ZirInst base;
4026
4027 Stage1ZirInst *target;
4028};
4029
4030struct Stage1AirInstIntToErr {
4031 Stage1AirInst base;
4032
4033 Stage1AirInst *target;
4034};
4035
4036struct Stage1ZirInstErrToInt {
4037 Stage1ZirInst base;
4038
4039 Stage1ZirInst *target;
4040};
4041
4042struct Stage1AirInstErrToInt {
4043 Stage1AirInst base;
4044
4045 Stage1AirInst *target;
4046};
4047
4048struct Stage1ZirInstCheckSwitchProngsRange {
4049 Stage1ZirInst *start;
4050 Stage1ZirInst *end;
4051};
4052
4053struct Stage1ZirInstCheckSwitchProngs {
4054 Stage1ZirInst base;
4055
4056 Stage1ZirInst *target_value;
4057 Stage1ZirInstCheckSwitchProngsRange *ranges;
4058 size_t range_count;
4059 AstNode* else_prong;
4060};
4061
4062struct Stage1ZirInstCheckStatementIsVoid {
4063 Stage1ZirInst base;
4064
4065 Stage1ZirInst *statement_value;
4066};
4067
4068struct Stage1ZirInstTypeName {
4069 Stage1ZirInst base;
4070
4071 Stage1ZirInst *type_value;
4072};
4073
4074struct Stage1ZirInstDeclRef {
4075 Stage1ZirInst base;
4076
4077 LVal lval;
4078 Tld *tld;
4079};
4080
4081struct Stage1ZirInstPanic {
4082 Stage1ZirInst base;
4083
4084 Stage1ZirInst *msg;
4085};
4086
4087struct Stage1AirInstPanic {
4088 Stage1AirInst base;
4089
4090 Stage1AirInst *msg;
4091};
4092
4093struct Stage1ZirInstTagName {
4094 Stage1ZirInst base;
4095
4096 Stage1ZirInst *target;
4097};
4098
4099struct Stage1AirInstTagName {
4100 Stage1AirInst base;
4101
4102 Stage1AirInst *target;
4103};
4104
4105struct Stage1ZirInstFieldParentPtr {
4106 Stage1ZirInst base;
4107
4108 Stage1ZirInst *type_value;
4109 Stage1ZirInst *field_name;
4110 Stage1ZirInst *field_ptr;
4111};
4112
4113struct Stage1AirInstFieldParentPtr {
4114 Stage1AirInst base;
4115
4116 Stage1AirInst *field_ptr;
4117 TypeStructField *field;
4118};
4119
4120struct Stage1ZirInstOffsetOf {
4121 Stage1ZirInst base;
4122
4123 Stage1ZirInst *type_value;
4124 Stage1ZirInst *field_name;
4125};
4126
4127struct Stage1ZirInstBitOffsetOf {
4128 Stage1ZirInst base;
4129
4130 Stage1ZirInst *type_value;
4131 Stage1ZirInst *field_name;
4132};
4133
4134struct Stage1ZirInstTypeInfo {
4135 Stage1ZirInst base;
4136
4137 Stage1ZirInst *type_value;
4138};
4139
4140struct Stage1ZirInstType {
4141 Stage1ZirInst base;
4142
4143 Stage1ZirInst *type_info;
4144};
4145
4146struct Stage1ZirInstHasField {
4147 Stage1ZirInst base;
4148
4149 Stage1ZirInst *container_type;
4150 Stage1ZirInst *field_name;
4151};
4152
4153struct Stage1ZirInstSetEvalBranchQuota {
4154 Stage1ZirInst base;
4155
4156 Stage1ZirInst *new_quota;
4157};
4158
4159struct Stage1ZirInstAlignCast {
4160 Stage1ZirInst base;
4161
4162 Stage1ZirInst *align_bytes;
4163 Stage1ZirInst *target;
4164};
4165
4166struct Stage1AirInstAlignCast {
4167 Stage1AirInst base;
4168
4169 Stage1AirInst *target;
4170};
4171
4172struct Stage1ZirInstAddrSpaceCast {
4173 Stage1ZirInst base;
4174
4175 Stage1ZirInst *addrspace;
4176 Stage1ZirInst *ptr;
4177};
4178
4179struct Stage1ZirInstSetAlignStack {
4180 Stage1ZirInst base;
4181
4182 Stage1ZirInst *align_bytes;
4183};
4184
4185struct Stage1ZirInstArgType {
4186 Stage1ZirInst base;
4187
4188 Stage1ZirInst *fn_type;
4189 Stage1ZirInst *arg_index;
4190};
4191
4192struct Stage1ZirInstExport {
4193 Stage1ZirInst base;
4194
4195 Stage1ZirInst *target;
4196 Stage1ZirInst *options;
4197};
4198
4199struct Stage1ZirInstExtern {
4200 Stage1ZirInst base;
4201
4202 Stage1ZirInst *type;
4203 Stage1ZirInst *options;
4204};
4205
4206struct Stage1AirInstExtern {
4207 Stage1AirInst base;
4208
4209 Buf *name;
4210 GlobalLinkageId linkage;
4211 bool is_thread_local;
4212};
4213
4214enum IrInstErrorReturnTraceOptional {
4215 IrInstErrorReturnTraceNull,
4216 IrInstErrorReturnTraceNonNull,
4217};
4218
4219struct Stage1ZirInstErrorReturnTrace {
4220 Stage1ZirInst base;
4221
4222 IrInstErrorReturnTraceOptional optional;
4223};
4224
4225struct Stage1AirInstErrorReturnTrace {
4226 Stage1AirInst base;
4227
4228 IrInstErrorReturnTraceOptional optional;
4229};
4230
4231struct Stage1ZirInstErrorUnion {
4232 Stage1ZirInst base;
4233
4234 Stage1ZirInst *err_set;
4235 Stage1ZirInst *payload;
4236 Buf *type_name;
4237};
4238
4239struct Stage1ZirInstAtomicRmw {
4240 Stage1ZirInst base;
4241
4242 Stage1ZirInst *operand_type;
4243 Stage1ZirInst *ptr;
4244 Stage1ZirInst *op;
4245 Stage1ZirInst *operand;
4246 Stage1ZirInst *ordering;
4247};
4248
4249struct Stage1AirInstAtomicRmw {
4250 Stage1AirInst base;
4251
4252 Stage1AirInst *ptr;
4253 Stage1AirInst *operand;
4254 AtomicRmwOp op;
4255 AtomicOrder ordering;
4256};
4257
4258struct Stage1ZirInstAtomicLoad {
4259 Stage1ZirInst base;
4260
4261 Stage1ZirInst *operand_type;
4262 Stage1ZirInst *ptr;
4263 Stage1ZirInst *ordering;
4264};
4265
4266struct Stage1AirInstAtomicLoad {
4267 Stage1AirInst base;
4268
4269 Stage1AirInst *ptr;
4270 AtomicOrder ordering;
4271};
4272
4273struct Stage1ZirInstAtomicStore {
4274 Stage1ZirInst base;
4275
4276 Stage1ZirInst *operand_type;
4277 Stage1ZirInst *ptr;
4278 Stage1ZirInst *value;
4279 Stage1ZirInst *ordering;
4280};
4281
4282struct Stage1AirInstAtomicStore {
4283 Stage1AirInst base;
4284
4285 Stage1AirInst *ptr;
4286 Stage1AirInst *value;
4287 AtomicOrder ordering;
4288};
4289
4290struct Stage1ZirInstSaveErrRetAddr {
4291 Stage1ZirInst base;
4292};
4293
4294struct Stage1AirInstSaveErrRetAddr {
4295 Stage1AirInst base;
4296};
4297
4298struct Stage1ZirInstAddImplicitReturnType {
4299 Stage1ZirInst base;
4300
4301 Stage1ZirInst *value;
4302 ResultLocReturn *result_loc_ret;
4303};
4304
4305// For float ops that take a single argument
4306struct Stage1ZirInstFloatOp {
4307 Stage1ZirInst base;
4308
4309 Stage1ZirInst *operand;
4310 BuiltinFnId fn_id;
4311};
4312
4313struct Stage1AirInstFloatOp {
4314 Stage1AirInst base;
4315
4316 Stage1AirInst *operand;
4317 BuiltinFnId fn_id;
4318};
4319
4320struct Stage1ZirInstCheckRuntimeScope {
4321 Stage1ZirInst base;
4322
4323 Stage1ZirInst *scope_is_comptime;
4324 Stage1ZirInst *is_comptime;
4325};
4326
4327struct Stage1ZirInstBswap {
4328 Stage1ZirInst base;
4329
4330 Stage1ZirInst *type;
4331 Stage1ZirInst *op;
4332};
4333
4334struct Stage1AirInstBswap {
4335 Stage1AirInst base;
4336
4337 Stage1AirInst *op;
4338};
4339
4340struct Stage1ZirInstBitReverse {
4341 Stage1ZirInst base;
4342
4343 Stage1ZirInst *type;
4344 Stage1ZirInst *op;
4345};
4346
4347struct Stage1AirInstBitReverse {
4348 Stage1AirInst base;
4349
4350 Stage1AirInst *op;
4351};
4352
4353struct Stage1AirInstArrayToVector {
4354 Stage1AirInst base;
4355
4356 Stage1AirInst *array;
4357};
4358
4359struct Stage1AirInstVectorToArray {
4360 Stage1AirInst base;
4361
4362 Stage1AirInst *vector;
4363 Stage1AirInst *result_loc;
4364};
4365
4366struct Stage1ZirInstShuffleVector {
4367 Stage1ZirInst base;
4368
4369 Stage1ZirInst *scalar_type;
4370 Stage1ZirInst *a;
4371 Stage1ZirInst *b;
4372 Stage1ZirInst *mask; // This is in zig-format, not llvm format
4373};
4374
4375struct Stage1AirInstShuffleVector {
4376 Stage1AirInst base;
4377
4378 Stage1AirInst *a;
4379 Stage1AirInst *b;
4380 Stage1AirInst *mask; // This is in zig-format, not llvm format
4381};
4382
4383struct Stage1ZirInstSelect {
4384 Stage1ZirInst base;
4385
4386 Stage1ZirInst *scalar_type;
4387 Stage1ZirInst *pred; // This is in zig-format, not llvm format
4388 Stage1ZirInst *a;
4389 Stage1ZirInst *b;
4390};
4391
4392struct Stage1AirInstSelect {
4393 Stage1AirInst base;
4394
4395 Stage1AirInst *pred; // This is in zig-format, not llvm format
4396 Stage1AirInst *a;
4397 Stage1AirInst *b;
4398};
4399
4400struct Stage1ZirInstSplat {
4401 Stage1ZirInst base;
4402
4403 Stage1ZirInst *len;
4404 Stage1ZirInst *scalar;
4405};
4406
4407struct Stage1AirInstSplat {
4408 Stage1AirInst base;
4409
4410 Stage1AirInst *scalar;
4411};
4412
4413struct Stage1AirInstAssertZero {
4414 Stage1AirInst base;
4415
4416 Stage1AirInst *target;
4417};
4418
4419struct Stage1AirInstAssertNonNull {
4420 Stage1AirInst base;
4421
4422 Stage1AirInst *target;
4423};
4424
4425struct Stage1ZirInstUnionInitNamedField {
4426 Stage1ZirInst base;
4427
4428 Stage1ZirInst *union_type;
4429 Stage1ZirInst *field_name;
4430 Stage1ZirInst *field_result_loc;
4431 Stage1ZirInst *result_loc;
4432};
4433
4434struct Stage1ZirInstHasDecl {
4435 Stage1ZirInst base;
4436
4437 Stage1ZirInst *container;
4438 Stage1ZirInst *name;
4439};
4440
4441struct Stage1ZirInstUndeclaredIdent {
4442 Stage1ZirInst base;
4443
4444 Buf *name;
4445};
4446
4447struct Stage1ZirInstAlloca {
4448 Stage1ZirInst base;
4449
4450 Stage1ZirInst *align;
4451 Stage1ZirInst *is_comptime;
4452 const char *name_hint;
4453};
4454
4455struct Stage1AirInstAlloca {
4456 Stage1AirInst base;
4457
4458 uint32_t align;
4459 const char *name_hint;
4460 size_t field_index;
4461};
4462
4463struct Stage1ZirInstEndExpr {
4464 Stage1ZirInst base;
4465
4466 Stage1ZirInst *value;
4467 ResultLoc *result_loc;
4468};
4469
4470// This one is for writing through the result pointer.
4471struct Stage1ZirInstResolveResult {
4472 Stage1ZirInst base;
4473
4474 ResultLoc *result_loc;
4475 Stage1ZirInst *ty;
4476};
4477
4478struct Stage1ZirInstResetResult {
4479 Stage1ZirInst base;
4480
4481 ResultLoc *result_loc;
4482};
4483
4484struct Stage1AirInstPtrOfArrayToSlice {
4485 Stage1AirInst base;
4486
4487 Stage1AirInst *operand;
4488 Stage1AirInst *result_loc;
4489};
4490
4491struct Stage1ZirInstSuspendBegin {
4492 Stage1ZirInst base;
4493};
4494
4495struct Stage1AirInstSuspendBegin {
4496 Stage1AirInst base;
4497
4498 LLVMBasicBlockRef resume_bb;
4499};
4500
4501struct Stage1ZirInstSuspendFinish {
4502 Stage1ZirInst base;
4503
4504 Stage1ZirInstSuspendBegin *begin;
4505};
4506
4507struct Stage1AirInstSuspendFinish {
4508 Stage1AirInst base;
4509
4510 Stage1AirInstSuspendBegin *begin;
4511};
4512
4513struct Stage1ZirInstAwait {
4514 Stage1ZirInst base;
4515
4516 Stage1ZirInst *frame;
4517 ResultLoc *result_loc;
4518 bool is_nosuspend;
4519};
4520
4521struct Stage1AirInstAwait {
4522 Stage1AirInst base;
4523
4524 Stage1AirInst *frame;
4525 Stage1AirInst *result_loc;
4526 ZigFn *target_fn;
4527 bool is_nosuspend;
4528};
4529
4530struct Stage1ZirInstResume {
4531 Stage1ZirInst base;
4532
4533 Stage1ZirInst *frame;
4534};
4535
4536struct Stage1AirInstResume {
4537 Stage1AirInst base;
4538
4539 Stage1AirInst *frame;
4540};
4541
4542enum SpillId {
4543 SpillIdInvalid,
4544 SpillIdRetErrCode,
4545};
4546
4547struct Stage1ZirInstSpillBegin {
4548 Stage1ZirInst base;
4549
4550 Stage1ZirInst *operand;
4551 SpillId spill_id;
4552};
4553
4554struct Stage1AirInstSpillBegin {
4555 Stage1AirInst base;
4556
4557 SpillId spill_id;
4558 Stage1AirInst *operand;
4559};
4560
4561struct Stage1ZirInstSpillEnd {
4562 Stage1ZirInst base;
4563
4564 Stage1ZirInstSpillBegin *begin;
4565};
4566
4567struct Stage1AirInstSpillEnd {
4568 Stage1AirInst base;
4569
4570 Stage1AirInstSpillBegin *begin;
4571};
4572
4573struct Stage1AirInstVectorExtractElem {
4574 Stage1AirInst base;
4575
4576 Stage1AirInst *vector;
4577 Stage1AirInst *index;
4578};
4579
4580enum ResultLocId {
4581 ResultLocIdInvalid,
4582 ResultLocIdNone,
4583 ResultLocIdVar,
4584 ResultLocIdReturn,
4585 ResultLocIdPeer,
4586 ResultLocIdPeerParent,
4587 ResultLocIdInstruction,
4588 ResultLocIdBitCast,
4589 ResultLocIdCast,
4590};
4591
4592// Additions to this struct may need to be handled in
4593// ir_reset_result
4594struct ResultLoc {
4595 ResultLocId id;
4596 bool written;
4597 bool allow_write_through_const;
4598 Stage1AirInst *resolved_loc; // result ptr
4599 Stage1ZirInst *source_instruction;
4600 Stage1AirInst *gen_instruction; // value to store to the result loc
4601 ZigType *implicit_elem_type;
4602};
4603
4604struct ResultLocNone {
4605 ResultLoc base;
4606};
4607
4608struct ResultLocVar {
4609 ResultLoc base;
4610
4611 ZigVar *var;
4612};
4613
4614struct ResultLocReturn {
4615 ResultLoc base;
4616
4617 bool implicit_return_type_done;
4618};
4619
4620struct IrSuspendPosition {
4621 size_t basic_block_index;
4622 size_t instruction_index;
4623};
4624
4625struct ResultLocPeerParent {
4626 ResultLoc base;
4627
4628 bool skipped;
4629 bool done_resuming;
4630 Stage1ZirBasicBlock *end_bb;
4631 ResultLoc *parent;
4632 ZigList<ResultLocPeer *> peers;
4633 ZigType *resolved_type;
4634 Stage1ZirInst *is_comptime;
4635};
4636
4637struct ResultLocPeer {
4638 ResultLoc base;
4639
4640 ResultLocPeerParent *parent;
4641 Stage1ZirBasicBlock *next_bb;
4642 IrSuspendPosition suspend_pos;
4643};
4644
4645// The result location is the source instruction
4646struct ResultLocInstruction {
4647 ResultLoc base;
4648};
4649
4650// The source_instruction is the destination type
4651struct ResultLocBitCast {
4652 ResultLoc base;
4653
4654 ResultLoc *parent;
4655};
4656
4657// The source_instruction is the destination type
4658struct ResultLocCast {
4659 ResultLoc base;
4660
4661 ResultLoc *parent;
4662};
4663
4664static const size_t slice_ptr_index = 0;
4665static const size_t slice_len_index = 1;
4666
4667static const size_t maybe_child_index = 0;
4668static const size_t maybe_null_index = 1;
4669
4670static const size_t err_union_payload_index = 0;
4671static const size_t err_union_err_index = 1;
4672
4673// label (grep this): [fn_frame_struct_layout]
4674static const size_t frame_fn_ptr_index = 0;
4675static const size_t frame_resume_index = 1;
4676static const size_t frame_awaiter_index = 2;
4677static const size_t frame_ret_start = 3;
4678
4679// TODO https://github.com/ziglang/zig/issues/3056
4680// We require this to be a power of 2 so that we can use shifting rather than
4681// remainder division.
4682static const size_t stack_trace_ptr_count = 32; // Must be a power of 2.
4683
4684#define NAMESPACE_SEP_CHAR '.'
4685#define NAMESPACE_SEP_STR "."
4686
4687#define CACHE_OUT_SUBDIR "o"
4688#define CACHE_HASH_SUBDIR "h"
4689
4690enum FloatMode {
4691 FloatModeStrict,
4692 FloatModeOptimized,
4693};
4694
4695enum FnWalkId {
4696 FnWalkIdAttrs,
4697 FnWalkIdCall,
4698 FnWalkIdTypes,
4699 FnWalkIdVars,
4700 FnWalkIdInits,
4701};
4702
4703struct FnWalkAttrs {
4704 ZigFn *fn;
4705 LLVMValueRef llvm_fn;
4706 unsigned gen_i;
4707};
4708
4709struct FnWalkCall {
4710 ZigList<LLVMValueRef> *gen_param_values;
4711 ZigList<ZigType *> *gen_param_types;
4712 Stage1AirInstCall *inst;
4713 bool is_var_args;
4714};
4715
4716struct FnWalkTypes {
4717 ZigList<ZigLLVMDIType *> *param_di_types;
4718 ZigList<LLVMTypeRef> *gen_param_types;
4719};
4720
4721struct FnWalkVars {
4722 ZigType *import;
4723 LLVMValueRef llvm_fn;
4724 ZigFn *fn;
4725 ZigVar *var;
4726 unsigned gen_i;
4727};
4728
4729struct FnWalkInits {
4730 LLVMValueRef llvm_fn;
4731 ZigFn *fn;
4732 unsigned gen_i;
4733};
4734
4735struct FnWalk {
4736 FnWalkId id;
4737 union {
4738 FnWalkAttrs attrs;
4739 FnWalkCall call;
4740 FnWalkTypes types;
4741 FnWalkVars vars;
4742 FnWalkInits inits;
4743 } data;
4744};
4745
4746#endif
src/stage1/analyze.cpp deleted-10443
...@@ -1,10443 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "analyze.hpp"
9#include "codegen.hpp"
10#include "error.hpp"
11#include "astgen.hpp"
12#include "ir.hpp"
13#include "ir_print.hpp"
14#include "os.hpp"
15#include "parser.hpp"
16#include "softfloat.hpp"
17#include "zig_llvm.h"
18
19
20static const size_t default_backward_branch_quota = 1000;
21
22static Error ATTRIBUTE_MUST_USE resolve_struct_type(CodeGen *g, ZigType *struct_type);
23
24static Error ATTRIBUTE_MUST_USE resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type);
25static Error ATTRIBUTE_MUST_USE resolve_struct_alignment(CodeGen *g, ZigType *struct_type);
26static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type);
27static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type);
28static Error ATTRIBUTE_MUST_USE resolve_union_alignment(CodeGen *g, ZigType *union_type);
29static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry);
30static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status);
31static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, ScopeDecls *dest_decls_scope);
32static void resolve_use_decl(CodeGen *g, TldUsingNamespace *tld_using_namespace, ScopeDecls *dest_decls_scope);
33static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame);
34
35// nullptr means not analyzed yet; this one means currently being analyzed
36static const AstNode *inferred_async_checking = reinterpret_cast<AstNode *>(0x1);
37// this one means analyzed and it's not async
38static const AstNode *inferred_async_none = reinterpret_cast<AstNode *>(0x2);
39
40static bool is_top_level_struct(ZigType *import) {
41 return import->id == ZigTypeIdStruct && import->data.structure.root_struct != nullptr;
42}
43
44static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ZigType *owner,
45 TokenIndex token, Buf *msg)
46{
47 assert(is_top_level_struct(owner));
48 RootStruct *root_struct = owner->data.structure.root_struct;
49 uint32_t byte_offset = root_struct->token_locs[token].offset;
50 ErrorMsg *err = err_msg_create_with_offset(root_struct->path, byte_offset,
51 buf_ptr(root_struct->source_code), msg);
52
53 err_msg_add_note(parent_msg, err);
54 return err;
55}
56
57ErrorMsg *add_token_error_offset(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg,
58 uint32_t bad_index)
59{
60 assert(is_top_level_struct(owner));
61 RootStruct *root_struct = owner->data.structure.root_struct;
62 uint32_t byte_offset = root_struct->token_locs[token].offset + bad_index;
63 ErrorMsg *err = err_msg_create_with_offset(root_struct->path, byte_offset,
64 buf_ptr(root_struct->source_code), msg);
65
66 g->errors.append(err);
67 g->trace_err = err;
68 return err;
69}
70
71ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg) {
72 return add_token_error_offset(g, owner, token, msg, 0);
73}
74
75ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
76 return add_token_error(g, node->owner, node->main_token, msg);
77}
78
79ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg) {
80 return add_error_note_token(g, parent_msg, node->owner, node->main_token, msg);
81}
82
83ZigType *new_type_table_entry(ZigTypeId id) {
84 ZigType *entry = heap::c_allocator.create<ZigType>();
85 entry->id = id;
86 return entry;
87}
88
89static ScopeDecls **get_container_scope_ptr(ZigType *type_entry) {
90 switch (type_entry->id) {
91 case ZigTypeIdStruct:
92 return &type_entry->data.structure.decls_scope;
93 case ZigTypeIdEnum:
94 return &type_entry->data.enumeration.decls_scope;
95 case ZigTypeIdUnion:
96 return &type_entry->data.unionation.decls_scope;
97 case ZigTypeIdOpaque:
98 return &type_entry->data.opaque.decls_scope;
99 default:
100 zig_unreachable();
101 }
102}
103
104static ScopeExpr *find_expr_scope(Scope *scope) {
105 for (;;) {
106 switch (scope->id) {
107 case ScopeIdExpr:
108 return reinterpret_cast<ScopeExpr *>(scope);
109 case ScopeIdDefer:
110 case ScopeIdDeferExpr:
111 case ScopeIdDecls:
112 case ScopeIdFnDef:
113 case ScopeIdCompTime:
114 case ScopeIdNoSuspend:
115 case ScopeIdVarDecl:
116 case ScopeIdCImport:
117 case ScopeIdSuspend:
118 case ScopeIdTypeOf:
119 case ScopeIdBlock:
120 return nullptr;
121 case ScopeIdLoop:
122 case ScopeIdRuntime:
123 scope = scope->parent;
124 continue;
125 }
126 }
127}
128
129static void update_progress_display(CodeGen *g) {
130 stage2_progress_update_node(g->sub_progress_node,
131 g->resolve_queue_index + g->fn_defs_index,
132 g->resolve_queue.length + g->fn_defs.length);
133}
134
135ScopeDecls *get_container_scope(ZigType *type_entry) {
136 return *get_container_scope_ptr(type_entry);
137}
138
139void init_scope(CodeGen *g, Scope *dest, ScopeId id, AstNode *source_node, Scope *parent) {
140 dest->codegen = g;
141 dest->id = id;
142 dest->source_node = source_node;
143 dest->parent = parent;
144}
145
146ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type,
147 ZigType *import, Buf *bare_name)
148{
149 ScopeDecls *scope = heap::c_allocator.create<ScopeDecls>();
150 init_scope(g, &scope->base, ScopeIdDecls, node, parent);
151 scope->decl_table.init(4);
152 scope->container_type = container_type;
153 scope->import = import;
154 scope->bare_name = bare_name;
155 return scope;
156}
157
158ScopeBlock *create_block_scope(CodeGen *g, AstNode *node, Scope *parent) {
159 assert(node->type == NodeTypeBlock);
160 ScopeBlock *scope = heap::c_allocator.create<ScopeBlock>();
161 init_scope(g, &scope->base, ScopeIdBlock, node, parent);
162 scope->name = node->data.block.name;
163 return scope;
164}
165
166ScopeDefer *create_defer_scope(CodeGen *g, AstNode *node, Scope *parent) {
167 assert(node->type == NodeTypeDefer);
168 ScopeDefer *scope = heap::c_allocator.create<ScopeDefer>();
169 init_scope(g, &scope->base, ScopeIdDefer, node, parent);
170 return scope;
171}
172
173ScopeDeferExpr *create_defer_expr_scope(CodeGen *g, AstNode *node, Scope *parent) {
174 assert(node->type == NodeTypeDefer);
175 ScopeDeferExpr *scope = heap::c_allocator.create<ScopeDeferExpr>();
176 init_scope(g, &scope->base, ScopeIdDeferExpr, node, parent);
177 return scope;
178}
179
180Scope *create_var_scope(CodeGen *g, AstNode *node, Scope *parent, ZigVar *var) {
181 ScopeVarDecl *scope = heap::c_allocator.create<ScopeVarDecl>();
182 init_scope(g, &scope->base, ScopeIdVarDecl, node, parent);
183 scope->var = var;
184 return &scope->base;
185}
186
187ScopeCImport *create_cimport_scope(CodeGen *g, AstNode *node, Scope *parent) {
188 assert(node->type == NodeTypeFnCallExpr);
189 ScopeCImport *scope = heap::c_allocator.create<ScopeCImport>();
190 init_scope(g, &scope->base, ScopeIdCImport, node, parent);
191 buf_resize(&scope->buf, 0);
192 return scope;
193}
194
195ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent) {
196 ScopeLoop *scope = heap::c_allocator.create<ScopeLoop>();
197 init_scope(g, &scope->base, ScopeIdLoop, node, parent);
198 if (node->type == NodeTypeWhileExpr) {
199 scope->name = node->data.while_expr.name;
200 } else if (node->type == NodeTypeForExpr) {
201 scope->name = node->data.for_expr.name;
202 } else {
203 zig_unreachable();
204 }
205 return scope;
206}
207
208Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, Stage1ZirInst *is_comptime) {
209 ScopeRuntime *scope = heap::c_allocator.create<ScopeRuntime>();
210 scope->is_comptime = is_comptime;
211 init_scope(g, &scope->base, ScopeIdRuntime, node, parent);
212 return &scope->base;
213}
214
215ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent) {
216 assert(node->type == NodeTypeSuspend);
217 ScopeSuspend *scope = heap::c_allocator.create<ScopeSuspend>();
218 init_scope(g, &scope->base, ScopeIdSuspend, node, parent);
219 return scope;
220}
221
222ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry) {
223 ScopeFnDef *scope = heap::c_allocator.create<ScopeFnDef>();
224 init_scope(g, &scope->base, ScopeIdFnDef, node, parent);
225 scope->fn_entry = fn_entry;
226 return scope;
227}
228
229Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent) {
230 ScopeCompTime *scope = heap::c_allocator.create<ScopeCompTime>();
231 init_scope(g, &scope->base, ScopeIdCompTime, node, parent);
232 return &scope->base;
233}
234
235Scope *create_nosuspend_scope(CodeGen *g, AstNode *node, Scope *parent) {
236 ScopeNoSuspend *scope = heap::c_allocator.create<ScopeNoSuspend>();
237 init_scope(g, &scope->base, ScopeIdNoSuspend, node, parent);
238 return &scope->base;
239}
240
241Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent) {
242 ScopeTypeOf *scope = heap::c_allocator.create<ScopeTypeOf>();
243 init_scope(g, &scope->base, ScopeIdTypeOf, node, parent);
244 return &scope->base;
245}
246
247ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent) {
248 ScopeExpr *scope = heap::c_allocator.create<ScopeExpr>();
249 init_scope(g, &scope->base, ScopeIdExpr, node, parent);
250 ScopeExpr *parent_expr = find_expr_scope(parent);
251 if (parent_expr != nullptr) {
252 size_t new_len = parent_expr->children_len + 1;
253 parent_expr->children_ptr = heap::c_allocator.reallocate_nonzero<ScopeExpr *>(
254 parent_expr->children_ptr, parent_expr->children_len, new_len);
255 parent_expr->children_ptr[parent_expr->children_len] = scope;
256 parent_expr->children_len = new_len;
257 }
258 return scope;
259}
260
261ZigType *get_scope_import(Scope *scope) {
262 while (scope) {
263 if (scope->id == ScopeIdDecls) {
264 ScopeDecls *decls_scope = (ScopeDecls *)scope;
265 assert(is_top_level_struct(decls_scope->import));
266 return decls_scope->import;
267 }
268 scope = scope->parent;
269 }
270 zig_unreachable();
271}
272
273ScopeTypeOf *get_scope_typeof(Scope *scope) {
274 while (scope) {
275 switch (scope->id) {
276 case ScopeIdTypeOf:
277 return reinterpret_cast<ScopeTypeOf *>(scope);
278 case ScopeIdFnDef:
279 case ScopeIdDecls:
280 return nullptr;
281 default:
282 scope = scope->parent;
283 continue;
284 }
285 }
286 zig_unreachable();
287}
288
289static ZigType *new_container_type_entry(CodeGen *g, ZigTypeId id, AstNode *source_node, Scope *parent_scope,
290 Buf *bare_name)
291{
292 ZigType *entry = new_type_table_entry(id);
293 *get_container_scope_ptr(entry) = create_decls_scope(g, source_node, parent_scope, entry,
294 get_scope_import(parent_scope), bare_name);
295 return entry;
296}
297
298static uint8_t bits_needed_for_unsigned(uint64_t x) {
299 if (x == 0) {
300 return 0;
301 }
302 uint8_t base = log2_u64(x);
303 uint64_t upper = (((uint64_t)1) << base) - 1;
304 return (upper >= x) ? base : (base + 1);
305}
306
307AstNode *type_decl_node(ZigType *type_entry) {
308 switch (type_entry->id) {
309 case ZigTypeIdInvalid:
310 zig_unreachable();
311 case ZigTypeIdStruct:
312 return type_entry->data.structure.decl_node;
313 case ZigTypeIdEnum:
314 return type_entry->data.enumeration.decl_node;
315 case ZigTypeIdUnion:
316 return type_entry->data.unionation.decl_node;
317 case ZigTypeIdFnFrame:
318 return type_entry->data.frame.fn->proto_node;
319 case ZigTypeIdOpaque:
320 case ZigTypeIdMetaType:
321 case ZigTypeIdVoid:
322 case ZigTypeIdBool:
323 case ZigTypeIdUnreachable:
324 case ZigTypeIdInt:
325 case ZigTypeIdFloat:
326 case ZigTypeIdPointer:
327 case ZigTypeIdArray:
328 case ZigTypeIdComptimeFloat:
329 case ZigTypeIdComptimeInt:
330 case ZigTypeIdEnumLiteral:
331 case ZigTypeIdUndefined:
332 case ZigTypeIdNull:
333 case ZigTypeIdOptional:
334 case ZigTypeIdErrorUnion:
335 case ZigTypeIdErrorSet:
336 case ZigTypeIdFn:
337 case ZigTypeIdBoundFn:
338 case ZigTypeIdVector:
339 case ZigTypeIdAnyFrame:
340 return nullptr;
341 }
342 zig_unreachable();
343}
344
345bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
346 switch (type_entry->id) {
347 case ZigTypeIdInvalid:
348 zig_unreachable();
349 case ZigTypeIdStruct:
350 return type_entry->data.structure.resolve_status >= status;
351 case ZigTypeIdUnion:
352 return type_entry->data.unionation.resolve_status >= status;
353 case ZigTypeIdEnum:
354 return type_entry->data.enumeration.resolve_status >= status;
355 case ZigTypeIdFnFrame:
356 switch (status) {
357 case ResolveStatusInvalid:
358 zig_unreachable();
359 case ResolveStatusBeingInferred:
360 zig_unreachable();
361 case ResolveStatusUnstarted:
362 case ResolveStatusZeroBitsKnown:
363 return true;
364 case ResolveStatusAlignmentKnown:
365 case ResolveStatusSizeKnown:
366 return type_entry->data.frame.locals_struct != nullptr;
367 case ResolveStatusLLVMFwdDecl:
368 case ResolveStatusLLVMFull:
369 return type_entry->llvm_type != nullptr;
370 }
371 zig_unreachable();
372 case ZigTypeIdOpaque:
373 return status < ResolveStatusSizeKnown;
374 case ZigTypeIdPointer:
375 switch (status) {
376 case ResolveStatusInvalid:
377 zig_unreachable();
378 case ResolveStatusBeingInferred:
379 zig_unreachable();
380 case ResolveStatusUnstarted:
381 return true;
382 case ResolveStatusZeroBitsKnown:
383 case ResolveStatusAlignmentKnown:
384 case ResolveStatusSizeKnown:
385 return type_entry->abi_size != SIZE_MAX;
386 case ResolveStatusLLVMFwdDecl:
387 case ResolveStatusLLVMFull:
388 return type_entry->llvm_type != nullptr;
389 }
390 zig_unreachable();
391 case ZigTypeIdMetaType:
392 case ZigTypeIdVoid:
393 case ZigTypeIdBool:
394 case ZigTypeIdUnreachable:
395 case ZigTypeIdInt:
396 case ZigTypeIdFloat:
397 case ZigTypeIdArray:
398 case ZigTypeIdComptimeFloat:
399 case ZigTypeIdComptimeInt:
400 case ZigTypeIdEnumLiteral:
401 case ZigTypeIdUndefined:
402 case ZigTypeIdNull:
403 case ZigTypeIdOptional:
404 case ZigTypeIdErrorUnion:
405 case ZigTypeIdErrorSet:
406 case ZigTypeIdFn:
407 case ZigTypeIdBoundFn:
408 case ZigTypeIdVector:
409 case ZigTypeIdAnyFrame:
410 return true;
411 }
412 zig_unreachable();
413}
414
415bool type_is_complete(ZigType *type_entry) {
416 return type_is_resolved(type_entry, ResolveStatusSizeKnown);
417}
418
419uint64_t type_size(CodeGen *g, ZigType *type_entry) {
420 assert(type_is_resolved(type_entry, ResolveStatusSizeKnown));
421 return type_entry->abi_size;
422}
423
424uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) {
425 assert(type_is_resolved(type_entry, ResolveStatusSizeKnown));
426 return type_entry->size_in_bits;
427}
428
429uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry) {
430 assert(type_is_resolved(type_entry, ResolveStatusAlignmentKnown));
431 return type_entry->abi_align;
432}
433
434static bool is_slice(ZigType *type) {
435 return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialSlice;
436}
437
438ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
439 return get_int_type(g, false, bits_needed_for_unsigned(x));
440}
441
442ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type) {
443 if (result_type != nullptr && result_type->any_frame_parent != nullptr) {
444 return result_type->any_frame_parent;
445 } else if (result_type == nullptr && g->builtin_types.entry_any_frame != nullptr) {
446 return g->builtin_types.entry_any_frame;
447 }
448
449 ZigType *entry = new_type_table_entry(ZigTypeIdAnyFrame);
450 entry->abi_size = g->builtin_types.entry_usize->abi_size;
451 entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
452 entry->abi_align = g->builtin_types.entry_usize->abi_align;
453 entry->data.any_frame.result_type = result_type;
454 buf_init_from_str(&entry->name, "anyframe");
455 if (result_type != nullptr) {
456 buf_appendf(&entry->name, "->%s", buf_ptr(&result_type->name));
457 }
458
459 if (result_type != nullptr) {
460 result_type->any_frame_parent = entry;
461 } else if (result_type == nullptr) {
462 g->builtin_types.entry_any_frame = entry;
463 }
464 return entry;
465}
466
467ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
468 if (fn->frame_type != nullptr) {
469 return fn->frame_type;
470 }
471
472 ZigType *entry = new_type_table_entry(ZigTypeIdFnFrame);
473 buf_resize(&entry->name, 0);
474 buf_appendf(&entry->name, "@Frame(%s)", buf_ptr(&fn->symbol_name));
475
476 entry->data.frame.fn = fn;
477
478 // Async function frames are always non-zero bits because they always have a resume index.
479 entry->abi_size = SIZE_MAX;
480 entry->size_in_bits = SIZE_MAX;
481
482 fn->frame_type = entry;
483 return entry;
484}
485
486static void append_ptr_type_attrs(Buf *type_name, ZigType *ptr_type) {
487 const char *const_str = ptr_type->data.pointer.is_const ? "const " : "";
488 const char *volatile_str = ptr_type->data.pointer.is_volatile ? "volatile " : "";
489 const char *allow_zero_str;
490 if (ptr_type->data.pointer.ptr_len == PtrLenC) {
491 assert(ptr_type->data.pointer.allow_zero);
492 allow_zero_str = "";
493 } else {
494 allow_zero_str = ptr_type->data.pointer.allow_zero ? "allowzero " : "";
495 }
496 if (ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.host_int_bytes != 0 ||
497 ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE)
498 {
499 buf_appendf(type_name, "align(");
500 if (ptr_type->data.pointer.explicit_alignment != 0) {
501 buf_appendf(type_name, "%" PRIu32, ptr_type->data.pointer.explicit_alignment);
502 }
503 if (ptr_type->data.pointer.host_int_bytes != 0) {
504 buf_appendf(type_name, ":%" PRIu32 ":%" PRIu32, ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes);
505 }
506 if (ptr_type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) {
507 buf_appendf(type_name, ":?");
508 } else if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) {
509 buf_appendf(type_name, ":%" PRIu32, ptr_type->data.pointer.vector_index);
510 }
511 buf_appendf(type_name, ") ");
512 }
513 buf_appendf(type_name, "%s%s%s", const_str, volatile_str, allow_zero_str);
514 if (ptr_type->data.pointer.inferred_struct_field != nullptr) {
515 buf_appendf(type_name, " field '%s' of %s)",
516 buf_ptr(ptr_type->data.pointer.inferred_struct_field->field_name),
517 buf_ptr(&ptr_type->data.pointer.inferred_struct_field->inferred_struct_type->name));
518 } else {
519 buf_appendf(type_name, "%s", buf_ptr(&ptr_type->data.pointer.child_type->name));
520 }
521}
522
523ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const,
524 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
525 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero,
526 uint32_t vector_index, InferredStructField *inferred_struct_field, ZigValue *sentinel)
527{
528 assert(ptr_len != PtrLenC || allow_zero);
529 assert(!type_is_invalid(child_type));
530 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
531
532 if (byte_alignment != 0) {
533 uint32_t abi_alignment = get_abi_alignment(g, child_type);
534 if (byte_alignment == abi_alignment)
535 byte_alignment = 0;
536 }
537
538 if (host_int_bytes != 0 && vector_index == VECTOR_INDEX_NONE) {
539 uint32_t child_type_bits = type_size_bits(g, child_type);
540 if (host_int_bytes * 8 == child_type_bits) {
541 assert(bit_offset_in_host == 0);
542 host_int_bytes = 0;
543 }
544 }
545
546 TypeId type_id = {};
547 ZigType **parent_pointer = nullptr;
548 if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||
549 allow_zero || vector_index != VECTOR_INDEX_NONE || inferred_struct_field != nullptr ||
550 sentinel != nullptr)
551 {
552 type_id.id = ZigTypeIdPointer;
553 type_id.data.pointer.codegen = g;
554 type_id.data.pointer.child_type = child_type;
555 type_id.data.pointer.is_const = is_const;
556 type_id.data.pointer.is_volatile = is_volatile;
557 type_id.data.pointer.alignment = byte_alignment;
558 type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;
559 type_id.data.pointer.host_int_bytes = host_int_bytes;
560 type_id.data.pointer.ptr_len = ptr_len;
561 type_id.data.pointer.allow_zero = allow_zero;
562 type_id.data.pointer.vector_index = vector_index;
563 type_id.data.pointer.inferred_struct_field = inferred_struct_field;
564 type_id.data.pointer.sentinel = sentinel;
565
566 auto existing_entry = g->type_table.maybe_get(type_id);
567 if (existing_entry)
568 return existing_entry->value;
569 } else {
570 assert(bit_offset_in_host == 0);
571 parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];
572 if (*parent_pointer) {
573 assert((*parent_pointer)->data.pointer.explicit_alignment == 0);
574 return *parent_pointer;
575 }
576 }
577
578 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
579
580 buf_resize(&entry->name, 0);
581 if (inferred_struct_field != nullptr) {
582 buf_appendf(&entry->name, "(");
583 }
584 switch (ptr_len) {
585 case PtrLenSingle:
586 assert(sentinel == nullptr);
587 buf_appendf(&entry->name, "*");
588 break;
589 case PtrLenUnknown:
590 buf_appendf(&entry->name, "[*");
591 break;
592 case PtrLenC:
593 assert(sentinel == nullptr);
594 buf_appendf(&entry->name, "[*c]");
595 break;
596 }
597 if (sentinel != nullptr) {
598 buf_appendf(&entry->name, ":");
599 render_const_value(g, &entry->name, sentinel);
600 }
601 switch (ptr_len) {
602 case PtrLenSingle:
603 case PtrLenC:
604 break;
605 case PtrLenUnknown:
606 buf_appendf(&entry->name, "]");
607 break;
608 }
609
610 if (inferred_struct_field != nullptr) {
611 entry->abi_size = SIZE_MAX;
612 entry->size_in_bits = SIZE_MAX;
613 entry->abi_align = UINT32_MAX;
614 } else if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
615 if (type_has_bits(g, child_type)) {
616 entry->abi_size = g->builtin_types.entry_usize->abi_size;
617 entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
618 entry->abi_align = g->builtin_types.entry_usize->abi_align;
619 } else {
620 assert(byte_alignment == 0);
621 entry->abi_size = 0;
622 entry->size_in_bits = 0;
623 entry->abi_align = 0;
624 }
625 } else {
626 entry->abi_size = SIZE_MAX;
627 entry->size_in_bits = SIZE_MAX;
628 entry->abi_align = UINT32_MAX;
629 }
630
631 entry->data.pointer.ptr_len = ptr_len;
632 entry->data.pointer.child_type = child_type;
633 entry->data.pointer.is_const = is_const;
634 entry->data.pointer.is_volatile = is_volatile;
635 entry->data.pointer.explicit_alignment = byte_alignment;
636 entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
637 entry->data.pointer.host_int_bytes = host_int_bytes;
638 entry->data.pointer.allow_zero = allow_zero;
639 entry->data.pointer.vector_index = vector_index;
640 entry->data.pointer.inferred_struct_field = inferred_struct_field;
641 entry->data.pointer.sentinel = sentinel;
642
643 append_ptr_type_attrs(&entry->name, entry);
644
645 if (parent_pointer) {
646 *parent_pointer = entry;
647 } else {
648 g->type_table.put(type_id, entry);
649 }
650 return entry;
651}
652
653ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
654 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
655 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)
656{
657 return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len,
658 byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE, nullptr, nullptr);
659}
660
661ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {
662 return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false,
663 VECTOR_INDEX_NONE, nullptr, nullptr);
664}
665
666ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
667 ZigType *result = get_optional_type2(g, child_type);
668 if (result == nullptr) {
669 codegen_report_errors_and_exit(g);
670 }
671 return result;
672}
673
674ZigType *get_optional_type2(CodeGen *g, ZigType *child_type) {
675 if (child_type->optional_parent != nullptr) {
676 return child_type->optional_parent;
677 }
678
679 Error err;
680 if ((err = type_resolve(g, child_type, ResolveStatusSizeKnown))) {
681 return nullptr;
682 }
683
684 ZigType *entry = new_type_table_entry(ZigTypeIdOptional);
685
686 buf_resize(&entry->name, 0);
687 buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name));
688
689 if (!type_has_bits(g, child_type)) {
690 entry->size_in_bits = g->builtin_types.entry_bool->size_in_bits;
691 entry->abi_size = g->builtin_types.entry_bool->abi_size;
692 entry->abi_align = g->builtin_types.entry_bool->abi_align;
693 } else if (type_is_nonnull_ptr(g, child_type) || child_type->id == ZigTypeIdErrorSet) {
694 // This is an optimization but also is necessary for calling C
695 // functions where all pointers are optional pointers.
696 // Function types are technically pointers.
697 entry->size_in_bits = child_type->size_in_bits;
698 entry->abi_size = child_type->abi_size;
699 entry->abi_align = child_type->abi_align;
700 } else {
701 // This value only matters if the type is legal in a packed struct, which is not
702 // true for optional types which did not fit the above 2 categories (zero bit child type,
703 // or nonnull ptr child type, or error set child type).
704 entry->size_in_bits = child_type->size_in_bits + 1;
705
706 // We're going to make a struct with the child type as the first field,
707 // and a bool as the second. Since the child type's abi alignment is guaranteed
708 // to be >= the bool's abi size (1 byte), the added size is exactly equal to the
709 // child type's ABI alignment.
710 assert(child_type->abi_align >= g->builtin_types.entry_bool->abi_size);
711 entry->abi_align = child_type->abi_align;
712 entry->abi_size = child_type->abi_size + child_type->abi_align;
713 }
714
715 entry->data.maybe.child_type = child_type;
716 entry->data.maybe.resolve_status = ResolveStatusSizeKnown;
717
718 child_type->optional_parent = entry;
719 return entry;
720}
721
722static size_t align_forward(size_t addr, size_t alignment) {
723 return (addr + alignment - 1) & ~(alignment - 1);
724}
725
726static size_t next_field_offset(size_t offset, size_t align_from_zero, size_t field_size, size_t next_field_align) {
727 // Convert offset to a pretend address which has the specified alignment.
728 size_t addr = offset + align_from_zero;
729 // March the address forward to respect the field alignment.
730 size_t aligned_addr = align_forward(addr + field_size, next_field_align);
731 // Convert back from pretend address to offset.
732 return aligned_addr - align_from_zero;
733}
734
735ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type) {
736 assert(err_set_type->id == ZigTypeIdErrorSet);
737 assert(!type_is_invalid(payload_type));
738
739 TypeId type_id = {};
740 type_id.id = ZigTypeIdErrorUnion;
741 type_id.data.error_union.err_set_type = err_set_type;
742 type_id.data.error_union.payload_type = payload_type;
743
744 auto existing_entry = g->type_table.maybe_get(type_id);
745 if (existing_entry) {
746 return existing_entry->value;
747 }
748
749 Error err;
750 if ((err = type_resolve(g, err_set_type, ResolveStatusSizeKnown)))
751 return g->builtin_types.entry_invalid;
752
753 if ((err = type_resolve(g, payload_type, ResolveStatusSizeKnown)))
754 return g->builtin_types.entry_invalid;
755
756 ZigType *entry = new_type_table_entry(ZigTypeIdErrorUnion);
757
758 buf_resize(&entry->name, 0);
759 buf_appendf(&entry->name, "%s!%s", buf_ptr(&err_set_type->name), buf_ptr(&payload_type->name));
760
761 entry->data.error_union.err_set_type = err_set_type;
762 entry->data.error_union.payload_type = payload_type;
763
764 if (!type_has_bits(g, payload_type)) {
765 if (type_has_bits(g, err_set_type)) {
766 entry->size_in_bits = err_set_type->size_in_bits;
767 entry->abi_size = err_set_type->abi_size;
768 entry->abi_align = err_set_type->abi_align;
769 } else {
770 entry->size_in_bits = 0;
771 entry->abi_size = 0;
772 entry->abi_align = 0;
773 }
774 } else if (!type_has_bits(g, err_set_type)) {
775 entry->size_in_bits = payload_type->size_in_bits;
776 entry->abi_size = payload_type->abi_size;
777 entry->abi_align = payload_type->abi_align;
778 } else {
779 entry->abi_align = max(err_set_type->abi_align, payload_type->abi_align);
780 size_t field_sizes[2];
781 size_t field_aligns[2];
782 field_sizes[err_union_err_index] = err_set_type->abi_size;
783 field_aligns[err_union_err_index] = err_set_type->abi_align;
784 field_sizes[err_union_payload_index] = payload_type->abi_size;
785 field_aligns[err_union_payload_index] = payload_type->abi_align;
786 size_t field2_offset = next_field_offset(0, entry->abi_align, field_sizes[0], field_aligns[1]);
787 entry->abi_size = next_field_offset(field2_offset, entry->abi_align, field_sizes[1], entry->abi_align);
788 entry->size_in_bits = entry->abi_size * 8;
789 entry->data.error_union.pad_bytes = entry->abi_size - (field2_offset + field_sizes[1]);
790 }
791
792 g->type_table.put(type_id, entry);
793 return entry;
794}
795
796ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, ZigValue *sentinel) {
797 Error err;
798
799 TypeId type_id = {};
800 type_id.id = ZigTypeIdArray;
801 type_id.data.array.codegen = g;
802 type_id.data.array.child_type = child_type;
803 type_id.data.array.size = array_size;
804 type_id.data.array.sentinel = sentinel;
805 auto existing_entry = g->type_table.maybe_get(type_id);
806 if (existing_entry) {
807 return existing_entry->value;
808 }
809
810 size_t full_array_size = array_size + ((sentinel != nullptr) ? 1 : 0);
811
812 if (full_array_size != 0 && (err = type_resolve(g, child_type, ResolveStatusSizeKnown))) {
813 codegen_report_errors_and_exit(g);
814 }
815
816 ZigType *entry = new_type_table_entry(ZigTypeIdArray);
817
818 buf_resize(&entry->name, 0);
819 buf_appendf(&entry->name, "[%" ZIG_PRI_u64, array_size);
820 if (sentinel != nullptr) {
821 buf_appendf(&entry->name, ":");
822 render_const_value(g, &entry->name, sentinel);
823 }
824 buf_appendf(&entry->name, "]%s", buf_ptr(&child_type->name));
825
826 entry->size_in_bits = child_type->size_in_bits * full_array_size;
827 entry->abi_align = (full_array_size == 0) ? 0 : child_type->abi_align;
828 entry->abi_size = child_type->abi_size * full_array_size;
829
830 entry->data.array.child_type = child_type;
831 entry->data.array.len = array_size;
832 entry->data.array.sentinel = sentinel;
833
834 g->type_table.put(type_id, entry);
835 return entry;
836}
837
838ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
839 Error err;
840 assert(ptr_type->id == ZigTypeIdPointer);
841 assert(ptr_type->data.pointer.ptr_len == PtrLenUnknown);
842
843 ZigType **parent_pointer = &ptr_type->data.pointer.slice_parent;
844 if (*parent_pointer) {
845 return *parent_pointer;
846 }
847
848 // We use the pointer type's abi size below, so we have to resolve it now.
849 if ((err = type_resolve(g, ptr_type, ResolveStatusSizeKnown))) {
850 codegen_report_errors_and_exit(g);
851 }
852
853 ZigType *entry = new_type_table_entry(ZigTypeIdStruct);
854
855 buf_resize(&entry->name, 0);
856 buf_appendf(&entry->name, "[");
857 if (ptr_type->data.pointer.sentinel != nullptr) {
858 buf_appendf(&entry->name, ":");
859 render_const_value(g, &entry->name, ptr_type->data.pointer.sentinel);
860 }
861 buf_appendf(&entry->name, "]");
862 append_ptr_type_attrs(&entry->name, ptr_type);
863
864 unsigned element_count = 2;
865 Buf *ptr_field_name = buf_create_from_str("ptr");
866 Buf *len_field_name = buf_create_from_str("len");
867
868 entry->data.structure.resolve_status = ResolveStatusSizeKnown;
869 entry->data.structure.layout = ContainerLayoutAuto;
870 entry->data.structure.special = StructSpecialSlice;
871 entry->data.structure.src_field_count = element_count;
872 entry->data.structure.gen_field_count = element_count;
873 entry->data.structure.fields = alloc_type_struct_fields(element_count);
874 entry->data.structure.fields_by_name.init(element_count);
875 entry->data.structure.fields[slice_ptr_index]->name = ptr_field_name;
876 entry->data.structure.fields[slice_ptr_index]->type_entry = ptr_type;
877 entry->data.structure.fields[slice_ptr_index]->src_index = slice_ptr_index;
878 entry->data.structure.fields[slice_ptr_index]->gen_index = 0;
879 entry->data.structure.fields[slice_ptr_index]->offset = 0;
880 entry->data.structure.fields[slice_len_index]->name = len_field_name;
881 entry->data.structure.fields[slice_len_index]->type_entry = g->builtin_types.entry_usize;
882 entry->data.structure.fields[slice_len_index]->src_index = slice_len_index;
883 entry->data.structure.fields[slice_len_index]->gen_index = 1;
884 entry->data.structure.fields[slice_len_index]->offset = ptr_type->abi_size;
885
886 entry->data.structure.fields_by_name.put(ptr_field_name, entry->data.structure.fields[slice_ptr_index]);
887 entry->data.structure.fields_by_name.put(len_field_name, entry->data.structure.fields[slice_len_index]);
888
889 switch (type_requires_comptime(g, ptr_type)) {
890 case ReqCompTimeInvalid:
891 zig_unreachable();
892 case ReqCompTimeNo:
893 break;
894 case ReqCompTimeYes:
895 entry->data.structure.requires_comptime = true;
896 }
897
898 if (!type_has_bits(g, ptr_type)) {
899 entry->data.structure.gen_field_count = 1;
900 entry->data.structure.fields[slice_ptr_index]->gen_index = SIZE_MAX;
901 entry->data.structure.fields[slice_len_index]->gen_index = 0;
902 }
903
904 if (type_has_bits(g, ptr_type)) {
905 entry->size_in_bits = ptr_type->size_in_bits + g->builtin_types.entry_usize->size_in_bits;
906 entry->abi_size = ptr_type->abi_size + g->builtin_types.entry_usize->abi_size;
907 entry->abi_align = ptr_type->abi_align;
908 } else {
909 entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
910 entry->abi_size = g->builtin_types.entry_usize->abi_size;
911 entry->abi_align = g->builtin_types.entry_usize->abi_align;
912 }
913
914 *parent_pointer = entry;
915 return entry;
916}
917
918static uint32_t node_line_onebased(AstNode *node) {
919 RootStruct *root_struct = node->owner->data.structure.root_struct;
920 assert(node->main_token < root_struct->token_count);
921 return root_struct->token_locs[node->main_token].line + 1;
922}
923
924static uint32_t node_column_onebased(AstNode *node) {
925 RootStruct *root_struct = node->owner->data.structure.root_struct;
926 assert(node->main_token < root_struct->token_count);
927 return root_struct->token_locs[node->main_token].column + 1;
928}
929
930ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *full_name,
931 Buf *bare_name)
932{
933 ZigType *entry = new_type_table_entry(ZigTypeIdOpaque);
934
935 buf_init_from_str(&entry->name, full_name);
936
937 ZigType *import = scope ? get_scope_import(scope) : nullptr;
938 unsigned line = source_node ? node_line_onebased(source_node) : 0;
939
940 // Note: duplicated in get_partial_container_type
941 entry->llvm_type = LLVMInt8Type();
942 entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder,
943 ZigLLVMTag_DW_structure_type(), full_name,
944 import ? ZigLLVMFileToScope(import->data.structure.root_struct->di_file) : nullptr,
945 import ? import->data.structure.root_struct->di_file : nullptr,
946 line);
947 entry->data.opaque.decl_node = source_node;
948 entry->data.opaque.bare_name = bare_name;
949 entry->data.opaque.decls_scope = create_decls_scope(
950 g, source_node, scope, entry, import, &entry->name);
951
952 // The actual size is unknown, but the value must not be 0 because that
953 // is how type_has_bits is determined.
954 entry->abi_size = SIZE_MAX;
955 entry->size_in_bits = SIZE_MAX;
956 entry->abi_align = 1;
957
958 return entry;
959}
960
961ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry) {
962 ZigType *fn_type = fn_entry->type_entry;
963 assert(fn_type->id == ZigTypeIdFn);
964 if (fn_type->data.fn.bound_fn_parent)
965 return fn_type->data.fn.bound_fn_parent;
966
967 ZigType *bound_fn_type = new_type_table_entry(ZigTypeIdBoundFn);
968 bound_fn_type->data.bound_fn.fn_type = fn_type;
969
970 buf_resize(&bound_fn_type->name, 0);
971 buf_appendf(&bound_fn_type->name, "(bound %s)", buf_ptr(&fn_type->name));
972
973 fn_type->data.fn.bound_fn_parent = bound_fn_type;
974 return bound_fn_type;
975}
976
977const char *calling_convention_name(CallingConvention cc) {
978 switch (cc) {
979 case CallingConventionUnspecified: return "Unspecified";
980 case CallingConventionC: return "C";
981 case CallingConventionNaked: return "Naked";
982 case CallingConventionAsync: return "Async";
983 case CallingConventionInterrupt: return "Interrupt";
984 case CallingConventionSignal: return "Signal";
985 case CallingConventionStdcall: return "Stdcall";
986 case CallingConventionFastcall: return "Fastcall";
987 case CallingConventionVectorcall: return "Vectorcall";
988 case CallingConventionThiscall: return "Thiscall";
989 case CallingConventionAPCS: return "APCS";
990 case CallingConventionAAPCS: return "AAPCS";
991 case CallingConventionAAPCSVFP: return "AAPCSVFP";
992 case CallingConventionInline: return "Inline";
993 case CallingConventionSysV: return "SysV";
994 case CallingConventionWin64: return "Win64";
995 case CallingConventionPtxKernel: return "PtxKernel";
996 case CallingConventionAmdgpuKernel: return "AmdgpuKernel";
997 }
998 zig_unreachable();
999}
1000
1001bool calling_convention_allows_zig_types(CallingConvention cc) {
1002 switch (cc) {
1003 case CallingConventionUnspecified:
1004 case CallingConventionAsync:
1005 case CallingConventionInline:
1006 case CallingConventionPtxKernel:
1007 return true;
1008 case CallingConventionC:
1009 case CallingConventionNaked:
1010 case CallingConventionInterrupt:
1011 case CallingConventionSignal:
1012 case CallingConventionStdcall:
1013 case CallingConventionFastcall:
1014 case CallingConventionVectorcall:
1015 case CallingConventionThiscall:
1016 case CallingConventionAPCS:
1017 case CallingConventionAAPCS:
1018 case CallingConventionAAPCSVFP:
1019 case CallingConventionSysV:
1020 case CallingConventionWin64:
1021 case CallingConventionAmdgpuKernel:
1022 return false;
1023 }
1024 zig_unreachable();
1025}
1026
1027const char *address_space_name(AddressSpace as) {
1028 switch (as) {
1029 case AddressSpaceGeneric: return "generic";
1030 case AddressSpaceGS: return "gs";
1031 case AddressSpaceFS: return "fs";
1032 case AddressSpaceSS: return "ss";
1033 case AddressSpaceGlobal: return "global";
1034 case AddressSpaceConstant: return "constant";
1035 case AddressSpaceParam: return "param";
1036 case AddressSpaceShared: return "shared";
1037 case AddressSpaceLocal: return "local";
1038 }
1039 zig_unreachable();
1040}
1041
1042ZigType *get_stack_trace_type(CodeGen *g) {
1043 if (g->stack_trace_type == nullptr) {
1044 g->stack_trace_type = get_builtin_type(g, "StackTrace");
1045 assertNoError(type_resolve(g, g->stack_trace_type, ResolveStatusZeroBitsKnown));
1046 }
1047 return g->stack_trace_type;
1048}
1049
1050bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
1051 if (fn_type_id->cc == CallingConventionUnspecified
1052 || fn_type_id->cc == CallingConventionInline) {
1053 return handle_is_ptr(g, fn_type_id->return_type);
1054 }
1055 if (fn_type_id->cc != CallingConventionC) {
1056 return false;
1057 }
1058 if (type_is_c_abi_int_bail(g, fn_type_id->return_type)) {
1059 return false;
1060 }
1061 if (g->zig_target->arch == ZigLLVM_x86 ||
1062 g->zig_target->arch == ZigLLVM_x86_64 ||
1063 target_is_arm(g->zig_target) ||
1064 target_is_riscv(g->zig_target) ||
1065 target_is_wasm(g->zig_target) ||
1066 target_is_sparc(g->zig_target) ||
1067 target_is_ppc(g->zig_target))
1068 {
1069 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
1070 return abi_class == X64CABIClass_MEMORY || abi_class == X64CABIClass_MEMORY_nobyval;
1071 } else if (g->zig_target->arch == ZigLLVM_mips || g->zig_target->arch == ZigLLVM_mipsel) {
1072 return false;
1073 }
1074 zig_panic("TODO implement C ABI for this architecture. See https://github.com/ziglang/zig/issues/1481");
1075}
1076
1077ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
1078 Error err;
1079 auto table_entry = g->fn_type_table.maybe_get(fn_type_id);
1080 if (table_entry) {
1081 return table_entry->value;
1082 }
1083 if (fn_type_id->return_type != nullptr) {
1084 if ((err = type_resolve(g, fn_type_id->return_type, ResolveStatusSizeKnown)))
1085 return g->builtin_types.entry_invalid;
1086 assert(fn_type_id->return_type->id != ZigTypeIdOpaque);
1087 } else {
1088 zig_panic("TODO implement inferred return types https://github.com/ziglang/zig/issues/447");
1089 }
1090
1091 ZigType *fn_type = new_type_table_entry(ZigTypeIdFn);
1092 fn_type->data.fn.fn_type_id = *fn_type_id;
1093
1094 // populate the name of the type
1095 buf_resize(&fn_type->name, 0);
1096 buf_appendf(&fn_type->name, "fn(");
1097 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
1098 FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
1099
1100 ZigType *param_type = param_info->type;
1101 const char *comma = (i == 0) ? "" : ", ";
1102 const char *noalias_str = param_info->is_noalias ? "noalias " : "";
1103 buf_appendf(&fn_type->name, "%s%s%s", comma, noalias_str, buf_ptr(&param_type->name));
1104 }
1105
1106 if (fn_type_id->is_var_args) {
1107 const char *comma = (fn_type_id->param_count == 0) ? "" : ", ";
1108 buf_appendf(&fn_type->name, "%s...", comma);
1109 }
1110 buf_appendf(&fn_type->name, ")");
1111 if (fn_type_id->alignment != 0) {
1112 buf_appendf(&fn_type->name, " align(%" PRIu32 ")", fn_type_id->alignment);
1113 }
1114 if (fn_type_id->cc != CallingConventionUnspecified) {
1115 buf_appendf(&fn_type->name, " callconv(.%s)", calling_convention_name(fn_type_id->cc));
1116 }
1117 buf_appendf(&fn_type->name, " %s", buf_ptr(&fn_type_id->return_type->name));
1118
1119 // The fn_type is a pointer; not to be confused with the raw function type.
1120 fn_type->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
1121 fn_type->abi_size = g->builtin_types.entry_usize->abi_size;
1122 fn_type->abi_align = g->builtin_types.entry_usize->abi_align;
1123
1124 g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type);
1125
1126 return fn_type;
1127}
1128
1129static ZigTypeId container_to_type(ContainerKind kind) {
1130 switch (kind) {
1131 case ContainerKindStruct:
1132 return ZigTypeIdStruct;
1133 case ContainerKindEnum:
1134 return ZigTypeIdEnum;
1135 case ContainerKindUnion:
1136 return ZigTypeIdUnion;
1137 case ContainerKindOpaque:
1138 return ZigTypeIdOpaque;
1139 }
1140 zig_unreachable();
1141}
1142
1143// This is like get_partial_container_type except it's for the implicit root struct of files.
1144static ZigType *get_root_container_type(CodeGen *g, const char *full_name, Buf *bare_name,
1145 RootStruct *root_struct)
1146{
1147 ZigType *entry = new_type_table_entry(ZigTypeIdStruct);
1148 entry->data.structure.decls_scope = create_decls_scope(g, nullptr, nullptr, entry, entry, bare_name);
1149 entry->data.structure.root_struct = root_struct;
1150 entry->data.structure.layout = ContainerLayoutAuto;
1151
1152 if (full_name[0] == '\0') {
1153 buf_init_from_str(&entry->name, "(root)");
1154 } else {
1155 buf_init_from_str(&entry->name, full_name);
1156 }
1157
1158 return entry;
1159}
1160
1161ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
1162 AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout)
1163{
1164 ZigTypeId type_id = container_to_type(kind);
1165 ZigType *entry = new_container_type_entry(g, type_id, decl_node, scope, bare_name);
1166
1167 switch (kind) {
1168 case ContainerKindStruct:
1169 entry->data.structure.decl_node = decl_node;
1170 entry->data.structure.layout = layout;
1171 break;
1172 case ContainerKindEnum:
1173 entry->data.enumeration.decl_node = decl_node;
1174 entry->data.enumeration.layout = layout;
1175 break;
1176 case ContainerKindUnion:
1177 entry->data.unionation.decl_node = decl_node;
1178 entry->data.unionation.layout = layout;
1179 break;
1180 case ContainerKindOpaque: {
1181 ZigType *import = scope ? get_scope_import(scope) : nullptr;
1182 unsigned line = decl_node ? node_line_onebased(decl_node) : 0;
1183 // Note: duplicated in get_opaque_type
1184 entry->llvm_type = LLVMInt8Type();
1185 entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder,
1186 ZigLLVMTag_DW_structure_type(), full_name,
1187 import ? ZigLLVMFileToScope(import->data.structure.root_struct->di_file) : nullptr,
1188 import ? import->data.structure.root_struct->di_file : nullptr,
1189 line);
1190 entry->data.opaque.decl_node = decl_node;
1191 entry->abi_size = SIZE_MAX;
1192 entry->size_in_bits = SIZE_MAX;
1193 entry->abi_align = 1;
1194 break;
1195 }
1196 }
1197
1198 buf_init_from_str(&entry->name, full_name);
1199
1200 return entry;
1201}
1202
1203ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
1204 Buf *type_name, UndefAllowed undef)
1205{
1206 Error err;
1207
1208 ZigValue *result = g->pass1_arena->create<ZigValue>();
1209 ZigValue *result_ptr = g->pass1_arena->create<ZigValue>();
1210 result->special = ConstValSpecialUndef;
1211 result->type = (type_entry == nullptr) ? g->builtin_types.entry_anytype : type_entry;
1212 result_ptr->special = ConstValSpecialStatic;
1213 result_ptr->type = get_pointer_to_type(g, result->type, false);
1214 result_ptr->data.x_ptr.mut = ConstPtrMutComptimeVar;
1215 result_ptr->data.x_ptr.special = ConstPtrSpecialRef;
1216 result_ptr->data.x_ptr.data.ref.pointee = result;
1217
1218 size_t backward_branch_count = 0;
1219 size_t backward_branch_quota = default_backward_branch_quota;
1220 if ((err = ir_eval_const_value(g, scope, node, result_ptr,
1221 &backward_branch_count, &backward_branch_quota,
1222 nullptr, nullptr, node, type_name, nullptr, nullptr, undef)))
1223 {
1224 return g->invalid_inst_gen->value;
1225 }
1226 return result;
1227}
1228
1229Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent_type,
1230 ZigValue *parent_type_val, bool *is_zero_bits)
1231{
1232 Error err;
1233 if (type_val->special != ConstValSpecialLazy) {
1234 assert(type_val->special == ConstValSpecialStatic);
1235
1236 // Self-referencing types via pointers are allowed and have non-zero size
1237 ZigType *ty = type_val->data.x_type;
1238 while (ty->id == ZigTypeIdPointer &&
1239 !ty->data.pointer.resolve_loop_flag_zero_bits)
1240 {
1241 ty = ty->data.pointer.child_type;
1242 }
1243
1244 if ((ty->id == ZigTypeIdStruct && ty->data.structure.resolve_loop_flag_zero_bits) ||
1245 (ty->id == ZigTypeIdUnion && ty->data.unionation.resolve_loop_flag_zero_bits) ||
1246 (ty->id == ZigTypeIdPointer && ty->data.pointer.resolve_loop_flag_zero_bits))
1247 {
1248 *is_zero_bits = false;
1249 return ErrorNone;
1250 }
1251
1252 if ((err = type_resolve(g, type_val->data.x_type, ResolveStatusZeroBitsKnown)))
1253 return err;
1254
1255 *is_zero_bits = (type_val->data.x_type->abi_size == 0);
1256 return ErrorNone;
1257 }
1258 switch (type_val->data.x_lazy->id) {
1259 case LazyValueIdInvalid:
1260 case LazyValueIdAlignOf:
1261 case LazyValueIdSizeOf:
1262 case LazyValueIdTypeInfoDecls:
1263 zig_unreachable();
1264 case LazyValueIdPtrType: {
1265 LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
1266
1267 if (parent_type_val == lazy_ptr_type->elem_type->value) {
1268 // Does a struct which contains a pointer field to itself have bits? Yes.
1269 *is_zero_bits = false;
1270 return ErrorNone;
1271 } else {
1272 if (parent_type_val == nullptr) {
1273 parent_type_val = type_val;
1274 }
1275 return type_val_resolve_zero_bits(g, lazy_ptr_type->elem_type->value, parent_type,
1276 parent_type_val, is_zero_bits);
1277 }
1278 }
1279 case LazyValueIdPtrTypeSimple:
1280 case LazyValueIdPtrTypeSimpleConst: {
1281 LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(type_val->data.x_lazy);
1282
1283 if (parent_type_val == lazy_ptr_type->elem_type->value) {
1284 // Does a struct which contains a pointer field to itself have bits? Yes.
1285 *is_zero_bits = false;
1286 return ErrorNone;
1287 } else {
1288 if (parent_type_val == nullptr) {
1289 parent_type_val = type_val;
1290 }
1291 return type_val_resolve_zero_bits(g, lazy_ptr_type->elem_type->value, parent_type,
1292 parent_type_val, is_zero_bits);
1293 }
1294 }
1295 case LazyValueIdArrayType: {
1296 LazyValueArrayType *lazy_array_type =
1297 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
1298
1299 // The sentinel counts as an extra element
1300 if (lazy_array_type->length == 0 && lazy_array_type->sentinel == nullptr) {
1301 *is_zero_bits = true;
1302 return ErrorNone;
1303 }
1304
1305 if ((err = type_val_resolve_zero_bits(g, lazy_array_type->elem_type->value,
1306 parent_type, nullptr, is_zero_bits)))
1307 return err;
1308
1309 return ErrorNone;
1310 }
1311 case LazyValueIdOptType:
1312 case LazyValueIdSliceType:
1313 case LazyValueIdErrUnionType:
1314 *is_zero_bits = false;
1315 return ErrorNone;
1316 case LazyValueIdFnType: {
1317 LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
1318 *is_zero_bits = lazy_fn_type->is_generic;
1319 return ErrorNone;
1320 }
1321 }
1322 zig_unreachable();
1323}
1324
1325Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_opaque_type) {
1326 if (type_val->special != ConstValSpecialLazy) {
1327 assert(type_val->special == ConstValSpecialStatic);
1328 if (type_val->data.x_type == g->builtin_types.entry_anytype) {
1329 *is_opaque_type = false;
1330 return ErrorNone;
1331 }
1332 *is_opaque_type = (type_val->data.x_type->id == ZigTypeIdOpaque);
1333 return ErrorNone;
1334 }
1335 switch (type_val->data.x_lazy->id) {
1336 case LazyValueIdInvalid:
1337 case LazyValueIdAlignOf:
1338 case LazyValueIdSizeOf:
1339 case LazyValueIdTypeInfoDecls:
1340 zig_unreachable();
1341 case LazyValueIdSliceType:
1342 case LazyValueIdPtrType:
1343 case LazyValueIdPtrTypeSimple:
1344 case LazyValueIdPtrTypeSimpleConst:
1345 case LazyValueIdFnType:
1346 case LazyValueIdOptType:
1347 case LazyValueIdErrUnionType:
1348 case LazyValueIdArrayType:
1349 *is_opaque_type = false;
1350 return ErrorNone;
1351 }
1352 zig_unreachable();
1353}
1354
1355static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type_val) {
1356 if (type_val->special != ConstValSpecialLazy) {
1357 return type_requires_comptime(g, type_val->data.x_type);
1358 }
1359 switch (type_val->data.x_lazy->id) {
1360 case LazyValueIdInvalid:
1361 case LazyValueIdAlignOf:
1362 case LazyValueIdSizeOf:
1363 case LazyValueIdTypeInfoDecls:
1364 zig_unreachable();
1365 case LazyValueIdSliceType: {
1366 LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);
1367 return type_val_resolve_requires_comptime(g, lazy_slice_type->elem_type->value);
1368 }
1369 case LazyValueIdPtrType: {
1370 LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
1371 return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type->value);
1372 }
1373 case LazyValueIdPtrTypeSimple:
1374 case LazyValueIdPtrTypeSimpleConst: {
1375 LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(type_val->data.x_lazy);
1376 return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type->value);
1377 }
1378 case LazyValueIdOptType: {
1379 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
1380 return type_val_resolve_requires_comptime(g, lazy_opt_type->payload_type->value);
1381 }
1382 case LazyValueIdArrayType: {
1383 LazyValueArrayType *lazy_array_type = reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
1384 return type_val_resolve_requires_comptime(g, lazy_array_type->elem_type->value);
1385 }
1386 case LazyValueIdFnType: {
1387 LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
1388 if (lazy_fn_type->is_generic)
1389 return ReqCompTimeYes;
1390 switch (type_val_resolve_requires_comptime(g, lazy_fn_type->return_type->value)) {
1391 case ReqCompTimeInvalid:
1392 return ReqCompTimeInvalid;
1393 case ReqCompTimeYes:
1394 return ReqCompTimeYes;
1395 case ReqCompTimeNo:
1396 break;
1397 }
1398 size_t param_count = lazy_fn_type->proto_node->data.fn_proto.params.length;
1399 for (size_t i = 0; i < param_count; i += 1) {
1400 AstNode *param_node = lazy_fn_type->proto_node->data.fn_proto.params.at(i);
1401 bool param_is_var_args = param_node->data.param_decl.is_var_args;
1402 if (param_is_var_args) break;
1403 switch (type_val_resolve_requires_comptime(g, lazy_fn_type->param_types[i]->value)) {
1404 case ReqCompTimeInvalid:
1405 return ReqCompTimeInvalid;
1406 case ReqCompTimeYes:
1407 return ReqCompTimeYes;
1408 case ReqCompTimeNo:
1409 break;
1410 }
1411 }
1412 return ReqCompTimeNo;
1413 }
1414 case LazyValueIdErrUnionType: {
1415 LazyValueErrUnionType *lazy_err_union_type =
1416 reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
1417 return type_val_resolve_requires_comptime(g, lazy_err_union_type->payload_type->value);
1418 }
1419 }
1420 zig_unreachable();
1421}
1422
1423Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ZigValue *type_val,
1424 size_t *abi_size, size_t *size_in_bits)
1425{
1426 Error err;
1427
1428start_over:
1429 if (type_val->special != ConstValSpecialLazy) {
1430 assert(type_val->special == ConstValSpecialStatic);
1431 ZigType *ty = type_val->data.x_type;
1432 if ((err = type_resolve(g, ty, ResolveStatusSizeKnown)))
1433 return err;
1434 *abi_size = ty->abi_size;
1435 *size_in_bits = ty->size_in_bits;
1436 return ErrorNone;
1437 }
1438 switch (type_val->data.x_lazy->id) {
1439 case LazyValueIdInvalid:
1440 case LazyValueIdAlignOf:
1441 case LazyValueIdSizeOf:
1442 case LazyValueIdTypeInfoDecls:
1443 zig_unreachable();
1444 case LazyValueIdSliceType: {
1445 LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);
1446 bool is_zero_bits;
1447 if ((err = type_val_resolve_zero_bits(g, lazy_slice_type->elem_type->value, nullptr,
1448 nullptr, &is_zero_bits)))
1449 {
1450 return err;
1451 }
1452 if (is_zero_bits) {
1453 *abi_size = g->builtin_types.entry_usize->abi_size;
1454 *size_in_bits = g->builtin_types.entry_usize->size_in_bits;
1455 } else {
1456 *abi_size = g->builtin_types.entry_usize->abi_size * 2;
1457 *size_in_bits = g->builtin_types.entry_usize->size_in_bits * 2;
1458 }
1459 return ErrorNone;
1460 }
1461 case LazyValueIdPtrType: {
1462 LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
1463 bool is_zero_bits;
1464 if ((err = type_val_resolve_zero_bits(g, lazy_ptr_type->elem_type->value, nullptr,
1465 nullptr, &is_zero_bits)))
1466 {
1467 return err;
1468 }
1469 if (is_zero_bits) {
1470 *abi_size = 0;
1471 *size_in_bits = 0;
1472 } else {
1473 *abi_size = g->builtin_types.entry_usize->abi_size;
1474 *size_in_bits = g->builtin_types.entry_usize->size_in_bits;
1475 }
1476 return ErrorNone;
1477 }
1478 case LazyValueIdPtrTypeSimple:
1479 case LazyValueIdPtrTypeSimpleConst: {
1480 LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(type_val->data.x_lazy);
1481 bool is_zero_bits;
1482 if ((err = type_val_resolve_zero_bits(g, lazy_ptr_type->elem_type->value, nullptr,
1483 nullptr, &is_zero_bits)))
1484 {
1485 return err;
1486 }
1487 if (is_zero_bits) {
1488 *abi_size = 0;
1489 *size_in_bits = 0;
1490 } else {
1491 *abi_size = g->builtin_types.entry_usize->abi_size;
1492 *size_in_bits = g->builtin_types.entry_usize->size_in_bits;
1493 }
1494 return ErrorNone;
1495 }
1496 case LazyValueIdFnType:
1497 *abi_size = g->builtin_types.entry_usize->abi_size;
1498 *size_in_bits = g->builtin_types.entry_usize->size_in_bits;
1499 return ErrorNone;
1500 case LazyValueIdOptType:
1501 case LazyValueIdErrUnionType:
1502 case LazyValueIdArrayType:
1503 if ((err = ir_resolve_lazy(g, source_node, type_val)))
1504 return err;
1505 goto start_over;
1506 }
1507 zig_unreachable();
1508}
1509
1510Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *type_val, uint32_t *abi_align) {
1511 Error err;
1512 if (type_val->special != ConstValSpecialLazy) {
1513 assert(type_val->special == ConstValSpecialStatic);
1514 ZigType *ty = type_val->data.x_type;
1515 if (ty->id == ZigTypeIdPointer) {
1516 *abi_align = g->builtin_types.entry_usize->abi_align;
1517 return ErrorNone;
1518 }
1519 if ((err = type_resolve(g, ty, ResolveStatusAlignmentKnown)))
1520 return err;
1521 *abi_align = ty->abi_align;
1522 return ErrorNone;
1523 }
1524 switch (type_val->data.x_lazy->id) {
1525 case LazyValueIdInvalid:
1526 case LazyValueIdAlignOf:
1527 case LazyValueIdSizeOf:
1528 case LazyValueIdTypeInfoDecls:
1529 zig_unreachable();
1530 case LazyValueIdSliceType:
1531 case LazyValueIdPtrType:
1532 case LazyValueIdPtrTypeSimple:
1533 case LazyValueIdPtrTypeSimpleConst:
1534 case LazyValueIdFnType:
1535 *abi_align = g->builtin_types.entry_usize->abi_align;
1536 return ErrorNone;
1537 case LazyValueIdOptType: {
1538 if ((err = ir_resolve_lazy(g, nullptr, type_val)))
1539 return err;
1540
1541 return type_val_resolve_abi_align(g, source_node, type_val, abi_align);
1542 }
1543 case LazyValueIdArrayType: {
1544 LazyValueArrayType *lazy_array_type =
1545 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
1546
1547 if (lazy_array_type->length + (lazy_array_type->sentinel != nullptr) != 0)
1548 return type_val_resolve_abi_align(g, source_node, lazy_array_type->elem_type->value, abi_align);
1549
1550 *abi_align = 0;
1551 return ErrorNone;
1552 }
1553 case LazyValueIdErrUnionType: {
1554 LazyValueErrUnionType *lazy_err_union_type =
1555 reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
1556 uint32_t payload_abi_align;
1557 if ((err = type_val_resolve_abi_align(g, source_node, lazy_err_union_type->payload_type->value,
1558 &payload_abi_align)))
1559 {
1560 return err;
1561 }
1562 *abi_align = (payload_abi_align > g->err_tag_type->abi_align) ?
1563 payload_abi_align : g->err_tag_type->abi_align;
1564 return ErrorNone;
1565 }
1566 }
1567 zig_unreachable();
1568}
1569
1570static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigValue *type_val) {
1571 if (type_val->special != ConstValSpecialLazy) {
1572 return type_has_one_possible_value(g, type_val->data.x_type);
1573 }
1574 switch (type_val->data.x_lazy->id) {
1575 case LazyValueIdInvalid:
1576 case LazyValueIdAlignOf:
1577 case LazyValueIdSizeOf:
1578 case LazyValueIdTypeInfoDecls:
1579 zig_unreachable();
1580 case LazyValueIdSliceType: // it has the len field
1581 case LazyValueIdOptType: // it has the optional bit
1582 case LazyValueIdFnType:
1583 return OnePossibleValueNo;
1584 case LazyValueIdArrayType: {
1585 LazyValueArrayType *lazy_array_type =
1586 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
1587 if (lazy_array_type->length == 0)
1588 return OnePossibleValueYes;
1589 return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value);
1590 }
1591 case LazyValueIdPtrType:
1592 case LazyValueIdPtrTypeSimple:
1593 case LazyValueIdPtrTypeSimpleConst: {
1594 Error err;
1595 bool zero_bits;
1596 if ((err = type_val_resolve_zero_bits(g, type_val, nullptr, nullptr, &zero_bits))) {
1597 return OnePossibleValueInvalid;
1598 }
1599 if (zero_bits) {
1600 return OnePossibleValueYes;
1601 } else {
1602 return OnePossibleValueNo;
1603 }
1604 }
1605 case LazyValueIdErrUnionType: {
1606 LazyValueErrUnionType *lazy_err_union_type =
1607 reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
1608 switch (type_val_resolve_has_one_possible_value(g, lazy_err_union_type->err_set_type->value)) {
1609 case OnePossibleValueInvalid:
1610 return OnePossibleValueInvalid;
1611 case OnePossibleValueNo:
1612 return OnePossibleValueNo;
1613 case OnePossibleValueYes:
1614 return type_val_resolve_has_one_possible_value(g, lazy_err_union_type->payload_type->value);
1615 }
1616 }
1617 }
1618 zig_unreachable();
1619}
1620
1621ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
1622 Error err;
1623 // Hot path for simple identifiers, to avoid unnecessary memory allocations.
1624 if (node->type == NodeTypeIdentifier) {
1625 RootStruct *root_struct = node->owner->data.structure.root_struct;
1626 Buf *variable_name = token_identifier_buf(root_struct, node->main_token);
1627 if (buf_eql_str(variable_name, "_"))
1628 goto abort_hot_path;
1629 ZigType *primitive_type;
1630 if ((err = get_primitive_type(g, variable_name, &primitive_type))) {
1631 goto abort_hot_path;
1632 } else {
1633 return primitive_type;
1634 }
1635abort_hot_path:;
1636 }
1637 ZigValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type,
1638 nullptr, UndefBad);
1639 if (type_is_invalid(result->type))
1640 return g->builtin_types.entry_invalid;
1641 src_assert(result->special == ConstValSpecialStatic, node);
1642 src_assert(result->data.x_type != nullptr, node);
1643 return result->data.x_type;
1644}
1645
1646ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
1647 ZigType *fn_type = new_type_table_entry(ZigTypeIdFn);
1648 buf_resize(&fn_type->name, 0);
1649 buf_appendf(&fn_type->name, "fn(");
1650 size_t i = 0;
1651 for (; i < fn_type_id->next_param_index; i += 1) {
1652 const char *comma_str = (i == 0) ? "" : ",";
1653 buf_appendf(&fn_type->name, "%s%s", comma_str,
1654 buf_ptr(&fn_type_id->param_info[i].type->name));
1655 }
1656 for (; i < fn_type_id->param_count; i += 1) {
1657 const char *comma_str = (i == 0) ? "" : ",";
1658 buf_appendf(&fn_type->name, "%sanytype", comma_str);
1659 }
1660 buf_append_str(&fn_type->name, ")");
1661 if (fn_type_id->cc != CallingConventionUnspecified) {
1662 buf_appendf(&fn_type->name, " callconv(.%s)", calling_convention_name(fn_type_id->cc));
1663 }
1664 buf_append_str(&fn_type->name, " anytype");
1665
1666 fn_type->data.fn.fn_type_id = *fn_type_id;
1667 fn_type->data.fn.is_generic = true;
1668 fn_type->abi_size = 0;
1669 fn_type->size_in_bits = 0;
1670 fn_type->abi_align = 0;
1671 return fn_type;
1672}
1673
1674CallingConvention cc_from_fn_proto(AstNodeFnProto *fn_proto) {
1675 // Compatible with the C ABI
1676 if (fn_proto->is_extern || fn_proto->is_export)
1677 return CallingConventionC;
1678
1679 if (fn_proto->fn_inline == FnInlineAlways)
1680 return CallingConventionInline;
1681
1682 return CallingConventionUnspecified;
1683}
1684
1685void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, CallingConvention cc, size_t param_count_alloc) {
1686 assert(proto_node->type == NodeTypeFnProto);
1687 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
1688
1689 fn_type_id->cc = cc;
1690 fn_type_id->param_count = fn_proto->params.length;
1691 fn_type_id->param_info = heap::c_allocator.allocate<FnTypeParamInfo>(param_count_alloc);
1692 fn_type_id->next_param_index = 0;
1693 fn_type_id->is_var_args = fn_proto->is_var_args;
1694}
1695
1696static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {
1697 ZigValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g),
1698 nullptr, UndefBad);
1699 if (type_is_invalid(align_result->type))
1700 return false;
1701
1702 uint32_t align_bytes = bigint_as_u32(&align_result->data.x_bigint);
1703 if (align_bytes == 0) {
1704 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
1705 return false;
1706 }
1707 if (!is_power_of_2(align_bytes)) {
1708 add_node_error(g, node, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes));
1709 return false;
1710 }
1711
1712 *result = align_bytes;
1713 return true;
1714}
1715
1716static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **out_buffer) {
1717 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
1718 PtrLenUnknown, 0, 0, 0, false);
1719 ZigType *str_type = get_slice_type(g, ptr_type);
1720 ZigValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr, UndefBad);
1721 if (type_is_invalid(result_val->type))
1722 return false;
1723
1724 ZigValue *ptr_field = result_val->data.x_struct.fields[slice_ptr_index];
1725 ZigValue *len_field = result_val->data.x_struct.fields[slice_len_index];
1726
1727 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
1728 ZigValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;
1729 if (array_val->data.x_array.special == ConstArraySpecialBuf) {
1730 *out_buffer = array_val->data.x_array.data.s_buf;
1731 return true;
1732 }
1733 expand_undef_array(g, array_val);
1734 size_t len = bigint_as_usize(&len_field->data.x_bigint);
1735 Buf *result = buf_alloc();
1736 buf_resize(result, len);
1737 for (size_t i = 0; i < len; i += 1) {
1738 size_t new_index = ptr_field->data.x_ptr.data.base_array.elem_index + i;
1739 ZigValue *char_val = &array_val->data.x_array.data.s_none.elements[new_index];
1740 if (char_val->special == ConstValSpecialUndef) {
1741 add_node_error(g, node, buf_sprintf("use of undefined value"));
1742 return false;
1743 }
1744 uint64_t big_c = bigint_as_u64(&char_val->data.x_bigint);
1745 assert(big_c <= UINT8_MAX);
1746 uint8_t c = (uint8_t)big_c;
1747 buf_ptr(result)[i] = c;
1748 }
1749 *out_buffer = result;
1750 return true;
1751}
1752
1753static Error emit_error_unless_type_allowed_in_packed_container(CodeGen *g, ZigType *type_entry,
1754 AstNode *source_node, const char* container_name)
1755{
1756 Error err;
1757 switch (type_entry->id) {
1758 case ZigTypeIdInvalid:
1759 zig_unreachable();
1760 case ZigTypeIdMetaType:
1761 case ZigTypeIdUnreachable:
1762 case ZigTypeIdComptimeFloat:
1763 case ZigTypeIdComptimeInt:
1764 case ZigTypeIdEnumLiteral:
1765 case ZigTypeIdUndefined:
1766 case ZigTypeIdNull:
1767 case ZigTypeIdErrorUnion:
1768 case ZigTypeIdErrorSet:
1769 case ZigTypeIdBoundFn:
1770 case ZigTypeIdOpaque:
1771 case ZigTypeIdFnFrame:
1772 case ZigTypeIdAnyFrame:
1773 add_node_error(g, source_node,
1774 buf_sprintf("type '%s' not allowed in packed %s; no guaranteed in-memory representation",
1775 buf_ptr(&type_entry->name), container_name));
1776 return ErrorSemanticAnalyzeFail;
1777 case ZigTypeIdVoid:
1778 case ZigTypeIdBool:
1779 case ZigTypeIdInt:
1780 case ZigTypeIdFloat:
1781 case ZigTypeIdPointer:
1782 case ZigTypeIdFn:
1783 case ZigTypeIdVector:
1784 return ErrorNone;
1785 case ZigTypeIdArray: {
1786 ZigType *elem_type = type_entry->data.array.child_type;
1787 if ((err = emit_error_unless_type_allowed_in_packed_container(g, elem_type, source_node, container_name)))
1788 return err;
1789 // TODO revisit this when doing https://github.com/ziglang/zig/issues/1512
1790 size_t abi_size_in_bits = type_size(g, type_entry) * 8;
1791 size_t size_in_bits = type_size_bits(g, type_entry);
1792 if (abi_size_in_bits == size_in_bits) return ErrorNone;
1793 add_node_error(g, source_node,
1794 buf_sprintf("array of '%s' not allowed in packed %s due to padding bits (must be padded from %zu to %zu bits)",
1795 buf_ptr(&elem_type->name), container_name, size_in_bits, abi_size_in_bits));
1796 return ErrorSemanticAnalyzeFail;
1797 }
1798 case ZigTypeIdStruct:
1799 switch (type_entry->data.structure.layout) {
1800 case ContainerLayoutPacked:
1801 case ContainerLayoutExtern:
1802 return ErrorNone;
1803 case ContainerLayoutAuto:
1804 add_node_error(g, source_node,
1805 buf_sprintf("non-packed, non-extern struct '%s' not allowed in packed %s; no guaranteed in-memory representation",
1806 buf_ptr(&type_entry->name), container_name));
1807 return ErrorSemanticAnalyzeFail;
1808 }
1809 zig_unreachable();
1810 case ZigTypeIdUnion:
1811 switch (type_entry->data.unionation.layout) {
1812 case ContainerLayoutPacked:
1813 case ContainerLayoutExtern:
1814 return ErrorNone;
1815 case ContainerLayoutAuto:
1816 add_node_error(g, source_node,
1817 buf_sprintf("non-packed, non-extern union '%s' not allowed in packed %s; no guaranteed in-memory representation",
1818 buf_ptr(&type_entry->name), container_name));
1819 return ErrorSemanticAnalyzeFail;
1820 }
1821 zig_unreachable();
1822 case ZigTypeIdOptional: {
1823 ZigType *ptr_type;
1824 if ((err = get_codegen_ptr_type(g, type_entry, &ptr_type))) return err;
1825 if (ptr_type != nullptr) return ErrorNone;
1826
1827 add_node_error(g, source_node,
1828 buf_sprintf("type '%s' not allowed in packed %s; no guaranteed in-memory representation",
1829 buf_ptr(&type_entry->name), container_name));
1830 return ErrorSemanticAnalyzeFail;
1831 }
1832 case ZigTypeIdEnum: {
1833 AstNode *decl_node = type_entry->data.enumeration.decl_node;
1834 if (decl_node->data.container_decl.init_arg_expr != nullptr) {
1835 return ErrorNone;
1836 }
1837 ErrorMsg *msg = add_node_error(g, source_node,
1838 buf_sprintf("type '%s' not allowed in packed %s; no guaranteed in-memory representation",
1839 buf_ptr(&type_entry->name), container_name));
1840 add_error_note(g, msg, decl_node,
1841 buf_sprintf("enum declaration does not specify an integer tag type"));
1842 return ErrorSemanticAnalyzeFail;
1843 }
1844 }
1845 zig_unreachable();
1846}
1847
1848static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType *type_entry,
1849 AstNode *source_node)
1850{
1851 return emit_error_unless_type_allowed_in_packed_container(g, type_entry, source_node, "struct");
1852}
1853
1854static Error emit_error_unless_type_allowed_in_packed_union(CodeGen *g, ZigType *type_entry,
1855 AstNode *source_node)
1856{
1857 return emit_error_unless_type_allowed_in_packed_container(g, type_entry, source_node, "union");
1858}
1859
1860Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, ExternPosition position, bool *result) {
1861 Error err;
1862 switch (type_entry->id) {
1863 case ZigTypeIdInvalid:
1864 zig_unreachable();
1865 case ZigTypeIdMetaType:
1866 case ZigTypeIdComptimeFloat:
1867 case ZigTypeIdComptimeInt:
1868 case ZigTypeIdEnumLiteral:
1869 case ZigTypeIdUndefined:
1870 case ZigTypeIdNull:
1871 case ZigTypeIdErrorUnion:
1872 case ZigTypeIdErrorSet:
1873 case ZigTypeIdBoundFn:
1874 case ZigTypeIdVoid:
1875 case ZigTypeIdFnFrame:
1876 case ZigTypeIdAnyFrame:
1877 *result = false;
1878 return ErrorNone;
1879 case ZigTypeIdUnreachable:
1880 *result = position == ExternPositionFunctionReturn;
1881 return ErrorNone;
1882 case ZigTypeIdOpaque:
1883 case ZigTypeIdBool:
1884 *result = true;
1885 return ErrorNone;
1886 case ZigTypeIdInt:
1887 switch (type_entry->data.integral.bit_count) {
1888 case 8:
1889 case 16:
1890 case 32:
1891 case 64:
1892 case 128:
1893 *result = true;
1894 return ErrorNone;
1895 default:
1896 *result = false;
1897 return ErrorNone;
1898 }
1899 case ZigTypeIdVector:
1900 return type_allowed_in_extern(g, type_entry->data.vector.elem_type, ExternPositionOther, result);
1901 case ZigTypeIdFloat:
1902 *result = true;
1903 return ErrorNone;
1904 case ZigTypeIdArray:
1905 if ((err = type_allowed_in_extern(g, type_entry->data.array.child_type, ExternPositionOther, result)))
1906 return err;
1907 *result = *result &&
1908 position != ExternPositionFunctionParameter &&
1909 position != ExternPositionFunctionReturn;
1910 return ErrorNone;
1911 case ZigTypeIdFn:
1912 *result = !calling_convention_allows_zig_types(type_entry->data.fn.fn_type_id.cc);
1913 return ErrorNone;
1914 case ZigTypeIdPointer:
1915 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
1916 return err;
1917 bool has_bits;
1918 if ((err = type_has_bits2(g, type_entry, &has_bits)))
1919 return err;
1920 *result = has_bits;
1921 return ErrorNone;
1922 case ZigTypeIdStruct:
1923 *result = type_entry->data.structure.layout == ContainerLayoutExtern ||
1924 type_entry->data.structure.layout == ContainerLayoutPacked;
1925 return ErrorNone;
1926 case ZigTypeIdOptional: {
1927 ZigType *child_type = type_entry->data.maybe.child_type;
1928 if (child_type->id != ZigTypeIdPointer && child_type->id != ZigTypeIdFn) {
1929 *result = false;
1930 return ErrorNone;
1931 }
1932 bool is_nonnull_ptr;
1933 if ((err = type_is_nonnull_ptr2(g, child_type, &is_nonnull_ptr)))
1934 return err;
1935 if (!is_nonnull_ptr) {
1936 *result = false;
1937 return ErrorNone;
1938 }
1939 return type_allowed_in_extern(g, child_type, ExternPositionOther, result);
1940 }
1941 case ZigTypeIdEnum: {
1942 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
1943 return err;
1944 ZigType *tag_int_type = type_entry->data.enumeration.tag_int_type;
1945 if (type_entry->data.enumeration.has_explicit_tag_type)
1946 return type_allowed_in_extern(g, tag_int_type, position, result);
1947 *result = type_entry->data.enumeration.layout == ContainerLayoutExtern ||
1948 type_entry->data.enumeration.layout == ContainerLayoutPacked;
1949 return ErrorNone;
1950 }
1951 case ZigTypeIdUnion:
1952 *result = type_entry->data.unionation.layout == ContainerLayoutExtern ||
1953 type_entry->data.unionation.layout == ContainerLayoutPacked;
1954 return ErrorNone;
1955 }
1956 zig_unreachable();
1957}
1958
1959ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry) {
1960 ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
1961 buf_resize(&err_set_type->name, 0);
1962 buf_appendf(&err_set_type->name, "@typeInfo(@typeInfo(@TypeOf(%s)).Fn.return_type.?).ErrorUnion.error_set", buf_ptr(&fn_entry->symbol_name));
1963 err_set_type->data.error_set.err_count = 0;
1964 err_set_type->data.error_set.errors = nullptr;
1965 err_set_type->data.error_set.infer_fn = fn_entry;
1966 err_set_type->data.error_set.incomplete = true;
1967 err_set_type->size_in_bits = g->builtin_types.entry_global_error_set->size_in_bits;
1968 err_set_type->abi_align = g->builtin_types.entry_global_error_set->abi_align;
1969 err_set_type->abi_size = g->builtin_types.entry_global_error_set->abi_size;
1970
1971 return err_set_type;
1972}
1973
1974// Sync this with get_llvm_cc in codegen.cpp
1975Error emit_error_unless_callconv_allowed_for_target(CodeGen *g, AstNode *source_node, CallingConvention cc) {
1976 Error ret = ErrorNone;
1977 const char *allowed_platforms = nullptr;
1978 switch (cc) {
1979 case CallingConventionUnspecified:
1980 case CallingConventionC:
1981 case CallingConventionNaked:
1982 case CallingConventionAsync:
1983 case CallingConventionInline:
1984 break;
1985 case CallingConventionInterrupt:
1986 if (g->zig_target->arch != ZigLLVM_x86
1987 && g->zig_target->arch != ZigLLVM_x86_64
1988 && g->zig_target->arch != ZigLLVM_avr
1989 && g->zig_target->arch != ZigLLVM_msp430)
1990 {
1991 allowed_platforms = "x86, x86_64, AVR, and MSP430";
1992 }
1993 break;
1994 case CallingConventionSignal:
1995 if (g->zig_target->arch != ZigLLVM_avr)
1996 allowed_platforms = "AVR";
1997 break;
1998 case CallingConventionStdcall:
1999 case CallingConventionFastcall:
2000 case CallingConventionThiscall:
2001 if (g->zig_target->arch != ZigLLVM_x86)
2002 allowed_platforms = "x86";
2003 break;
2004 case CallingConventionVectorcall:
2005 if (g->zig_target->arch != ZigLLVM_x86
2006 && !(target_is_arm(g->zig_target) && target_arch_pointer_bit_width(g->zig_target->arch) == 64))
2007 {
2008 allowed_platforms = "x86 and AArch64";
2009 }
2010 break;
2011 case CallingConventionAPCS:
2012 case CallingConventionAAPCS:
2013 case CallingConventionAAPCSVFP:
2014 if (!target_is_arm(g->zig_target))
2015 allowed_platforms = "ARM";
2016 break;
2017 case CallingConventionSysV:
2018 case CallingConventionWin64:
2019 if (g->zig_target->arch != ZigLLVM_x86_64)
2020 allowed_platforms = "x86_64";
2021 break;
2022 case CallingConventionPtxKernel:
2023 if (g->zig_target->arch != ZigLLVM_nvptx
2024 && g->zig_target->arch != ZigLLVM_nvptx64)
2025 {
2026 allowed_platforms = "nvptx and nvptx64";
2027 }
2028 break;
2029 case CallingConventionAmdgpuKernel:
2030 if (g->zig_target->arch != ZigLLVM_amdgcn)
2031 allowed_platforms = "amdgcn and amdpal";
2032
2033 }
2034 if (allowed_platforms != nullptr) {
2035 add_node_error(g, source_node, buf_sprintf(
2036 "callconv '%s' is only available on %s, not %s",
2037 calling_convention_name(cc), allowed_platforms,
2038 target_arch_name(g->zig_target->arch)));
2039 ret = ErrorSemanticAnalyzeFail;
2040 }
2041 return ret;
2042}
2043
2044static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope, ZigFn *fn_entry,
2045 CallingConvention cc)
2046{
2047 assert(proto_node->type == NodeTypeFnProto);
2048 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
2049 Error err;
2050
2051 FnTypeId fn_type_id = {0};
2052 init_fn_type_id(&fn_type_id, proto_node, cc, proto_node->data.fn_proto.params.length);
2053
2054 for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) {
2055 AstNode *param_node = fn_proto->params.at(fn_type_id.next_param_index);
2056 assert(param_node->type == NodeTypeParamDecl);
2057
2058 bool param_is_comptime = param_node->data.param_decl.is_comptime;
2059 bool param_is_var_args = param_node->data.param_decl.is_var_args;
2060
2061 if (param_is_comptime) {
2062 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
2063 add_node_error(g, param_node,
2064 buf_sprintf("comptime parameter not allowed in function with calling convention '%s'",
2065 calling_convention_name(fn_type_id.cc)));
2066 return g->builtin_types.entry_invalid;
2067 }
2068 if (param_node->data.param_decl.type != nullptr) {
2069 ZigType *type_entry = analyze_type_expr(g, child_scope, param_node->data.param_decl.type);
2070 if (type_is_invalid(type_entry)) {
2071 return g->builtin_types.entry_invalid;
2072 }
2073 FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
2074 param_info->type = type_entry;
2075 param_info->is_noalias = param_node->data.param_decl.is_noalias;
2076 fn_type_id.next_param_index += 1;
2077 }
2078
2079 return get_generic_fn_type(g, &fn_type_id);
2080 } else if (param_is_var_args) {
2081 if (fn_type_id.cc == CallingConventionC) {
2082 fn_type_id.param_count = fn_type_id.next_param_index;
2083 continue;
2084 } else {
2085 add_node_error(g, param_node,
2086 buf_sprintf("var args only allowed in functions with C calling convention"));
2087 return g->builtin_types.entry_invalid;
2088 }
2089 } else if (param_node->data.param_decl.anytype_token != 0) {
2090 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
2091 add_node_error(g, param_node,
2092 buf_sprintf("parameter of type 'anytype' not allowed in function with calling convention '%s'",
2093 calling_convention_name(fn_type_id.cc)));
2094 return g->builtin_types.entry_invalid;
2095 }
2096 return get_generic_fn_type(g, &fn_type_id);
2097 }
2098
2099 ZigType *type_entry = analyze_type_expr(g, child_scope, param_node->data.param_decl.type);
2100 if (type_is_invalid(type_entry)) {
2101 return g->builtin_types.entry_invalid;
2102 }
2103 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
2104 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
2105 return g->builtin_types.entry_invalid;
2106 if (!type_has_bits(g, type_entry)) {
2107 add_node_error(g, param_node->data.param_decl.type,
2108 buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'",
2109 buf_ptr(&type_entry->name), calling_convention_name(fn_type_id.cc)));
2110 return g->builtin_types.entry_invalid;
2111 }
2112 }
2113
2114 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
2115 bool ok_type;
2116 if ((err = type_allowed_in_extern(g, type_entry, ExternPositionFunctionParameter, &ok_type)))
2117 return g->builtin_types.entry_invalid;
2118 if (!ok_type) {
2119 add_node_error(g, param_node->data.param_decl.type,
2120 buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
2121 buf_ptr(&type_entry->name),
2122 calling_convention_name(fn_type_id.cc)));
2123 return g->builtin_types.entry_invalid;
2124 }
2125 }
2126
2127 if(!is_valid_param_type(type_entry)){
2128 if(type_entry->id == ZigTypeIdOpaque){
2129 add_node_error(g, param_node->data.param_decl.type,
2130 buf_sprintf("parameter of opaque type '%s' not allowed", buf_ptr(&type_entry->name)));
2131 } else {
2132 add_node_error(g, param_node->data.param_decl.type,
2133 buf_sprintf("parameter of type '%s' not allowed", buf_ptr(&type_entry->name)));
2134 }
2135
2136 return g->builtin_types.entry_invalid;
2137 }
2138
2139 switch (type_requires_comptime(g, type_entry)) {
2140 case ReqCompTimeNo:
2141 break;
2142 case ReqCompTimeYes:
2143 add_node_error(g, param_node->data.param_decl.type,
2144 buf_sprintf("parameter of type '%s' must be declared comptime",
2145 buf_ptr(&type_entry->name)));
2146 return g->builtin_types.entry_invalid;
2147 case ReqCompTimeInvalid:
2148 return g->builtin_types.entry_invalid;
2149 }
2150
2151 FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
2152 param_info->type = type_entry;
2153 param_info->is_noalias = param_node->data.param_decl.is_noalias;
2154 }
2155
2156 if (fn_proto->align_expr != nullptr) {
2157 if (target_is_wasm(g->zig_target)) {
2158 // In Wasm, specifying alignment of function pointers makes little sense
2159 // since function pointers are in fact indices to a Wasm table, therefore
2160 // any alignment check on those is invalid. This can cause unexpected
2161 // behaviour when checking expected alignment with `@ptrToInt(fn_ptr)`
2162 // or similar. This commit proposes to make `align` expressions a
2163 // compile error when compiled to Wasm architecture.
2164 //
2165 // Some references:
2166 // [1] [Mozilla: WebAssembly Tables](https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format#WebAssembly_tables)
2167 // [2] [Sunfishcode's Wasm Ref Manual](https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#indirect-call)
2168 add_node_error(g, fn_proto->align_expr,
2169 buf_sprintf("align(N) expr is not allowed on function prototypes in wasm32/wasm64"));
2170 return g->builtin_types.entry_invalid;
2171 }
2172 if (!analyze_const_align(g, child_scope, fn_proto->align_expr, &fn_type_id.alignment)) {
2173 return g->builtin_types.entry_invalid;
2174 }
2175 fn_entry->align_bytes = fn_type_id.alignment;
2176 }
2177
2178 if (proto_node->data.fn_proto.callconv_expr != nullptr) {
2179 if ((err = emit_error_unless_callconv_allowed_for_target(g, proto_node->data.fn_proto.callconv_expr, cc)))
2180 return g->builtin_types.entry_invalid;
2181 }
2182
2183 ZigType *specified_return_type = analyze_type_expr(g, child_scope, fn_proto->return_type);
2184 if (type_is_invalid(specified_return_type)) {
2185 fn_type_id.return_type = g->builtin_types.entry_invalid;
2186 return g->builtin_types.entry_invalid;
2187 }
2188
2189 if(!is_valid_return_type(specified_return_type)){
2190 ErrorMsg* msg = add_node_error(g, fn_proto->return_type,
2191 buf_sprintf("%s return type '%s' not allowed", type_id_name(specified_return_type->id), buf_ptr(&specified_return_type->name)));
2192 Tld *tld = find_decl(g, &fn_entry->fndef_scope->base, &specified_return_type->name);
2193 if (tld != nullptr) {
2194 add_error_note(g, msg, tld->source_node, buf_sprintf("type declared here"));
2195 }
2196 return g->builtin_types.entry_invalid;
2197 }
2198
2199 if (fn_proto->auto_err_set) {
2200 ZigType *inferred_err_set_type = get_auto_err_set_type(g, fn_entry);
2201 if ((err = type_resolve(g, specified_return_type, ResolveStatusSizeKnown)))
2202 return g->builtin_types.entry_invalid;
2203 fn_type_id.return_type = get_error_union_type(g, inferred_err_set_type, specified_return_type);
2204 } else {
2205 fn_type_id.return_type = specified_return_type;
2206 }
2207
2208 if (!calling_convention_allows_zig_types(fn_type_id.cc) &&
2209 fn_type_id.return_type->id != ZigTypeIdVoid)
2210 {
2211 if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusSizeKnown)))
2212 return g->builtin_types.entry_invalid;
2213 bool ok_type;
2214 if ((err = type_allowed_in_extern(g, fn_type_id.return_type, ExternPositionFunctionReturn, &ok_type)))
2215 return g->builtin_types.entry_invalid;
2216 if (!ok_type) {
2217 add_node_error(g, fn_proto->return_type,
2218 buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",
2219 buf_ptr(&fn_type_id.return_type->name),
2220 calling_convention_name(fn_type_id.cc)));
2221 return g->builtin_types.entry_invalid;
2222 }
2223 }
2224
2225 switch (type_requires_comptime(g, fn_type_id.return_type)) {
2226 case ReqCompTimeInvalid:
2227 return g->builtin_types.entry_invalid;
2228 case ReqCompTimeYes:
2229 return get_generic_fn_type(g, &fn_type_id);
2230 case ReqCompTimeNo:
2231 break;
2232 }
2233
2234 return get_fn_type(g, &fn_type_id);
2235}
2236
2237bool is_valid_return_type(ZigType* type) {
2238 switch (type->id) {
2239 case ZigTypeIdInvalid:
2240 case ZigTypeIdUndefined:
2241 case ZigTypeIdNull:
2242 case ZigTypeIdOpaque:
2243 return false;
2244 default:
2245 return true;
2246 }
2247 zig_unreachable();
2248}
2249
2250bool is_valid_param_type(ZigType* type) {
2251 switch (type->id) {
2252 case ZigTypeIdInvalid:
2253 case ZigTypeIdUndefined:
2254 case ZigTypeIdNull:
2255 case ZigTypeIdOpaque:
2256 case ZigTypeIdUnreachable:
2257 return false;
2258 default:
2259 return true;
2260 }
2261 zig_unreachable();
2262}
2263
2264bool type_is_invalid(ZigType *type_entry) {
2265 switch (type_entry->id) {
2266 case ZigTypeIdInvalid:
2267 return true;
2268 case ZigTypeIdStruct:
2269 return type_entry->data.structure.resolve_status == ResolveStatusInvalid;
2270 case ZigTypeIdUnion:
2271 return type_entry->data.unionation.resolve_status == ResolveStatusInvalid;
2272 case ZigTypeIdEnum:
2273 return type_entry->data.enumeration.resolve_status == ResolveStatusInvalid;
2274 case ZigTypeIdFnFrame:
2275 return type_entry->data.frame.reported_loop_err;
2276 default:
2277 return false;
2278 }
2279 zig_unreachable();
2280}
2281
2282struct SrcField {
2283 const char *name;
2284 ZigType *ty;
2285 unsigned align;
2286};
2287
2288static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fields[], size_t field_count,
2289 unsigned min_abi_align)
2290{
2291 ZigType *struct_type = new_type_table_entry(ZigTypeIdStruct);
2292
2293 buf_init_from_str(&struct_type->name, type_name);
2294
2295 struct_type->data.structure.src_field_count = field_count;
2296 struct_type->data.structure.gen_field_count = 0;
2297 struct_type->data.structure.resolve_status = ResolveStatusSizeKnown;
2298 struct_type->data.structure.fields = alloc_type_struct_fields(field_count);
2299 struct_type->data.structure.fields_by_name.init(field_count);
2300
2301 size_t abi_align = min_abi_align;
2302 for (size_t i = 0; i < field_count; i += 1) {
2303 TypeStructField *field = struct_type->data.structure.fields[i];
2304 field->name = buf_create_from_str(fields[i].name);
2305 field->type_entry = fields[i].ty;
2306 field->src_index = i;
2307 field->align = fields[i].align;
2308
2309 if (type_has_bits(g, field->type_entry)) {
2310 assert(type_is_resolved(field->type_entry, ResolveStatusSizeKnown));
2311 unsigned field_abi_align = max(field->align, field->type_entry->abi_align);
2312 if (field_abi_align > abi_align) {
2313 abi_align = field_abi_align;
2314 }
2315 }
2316
2317 auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field);
2318 assert(prev_entry == nullptr);
2319 }
2320
2321 size_t next_offset = 0;
2322 for (size_t i = 0; i < field_count; i += 1) {
2323 TypeStructField *field = struct_type->data.structure.fields[i];
2324 if (!type_has_bits(g, field->type_entry))
2325 continue;
2326
2327 field->offset = next_offset;
2328
2329 // find the next non-zero-byte field for offset calculations
2330 size_t next_src_field_index = i + 1;
2331 for (; next_src_field_index < field_count; next_src_field_index += 1) {
2332 if (type_has_bits(g, struct_type->data.structure.fields[next_src_field_index]->type_entry))
2333 break;
2334 }
2335 size_t next_abi_align;
2336 if (next_src_field_index == field_count) {
2337 next_abi_align = abi_align;
2338 } else {
2339 next_abi_align = max(fields[next_src_field_index].align,
2340 struct_type->data.structure.fields[next_src_field_index]->type_entry->abi_align);
2341 }
2342 next_offset = next_field_offset(next_offset, abi_align, field->type_entry->abi_size, next_abi_align);
2343 }
2344
2345 struct_type->abi_align = abi_align;
2346 struct_type->abi_size = next_offset;
2347 struct_type->size_in_bits = next_offset * 8;
2348
2349 return struct_type;
2350}
2351
2352static size_t get_store_size_bytes(size_t size_in_bits) {
2353 return (size_in_bits + 7) / 8;
2354}
2355
2356static size_t get_abi_align_bytes(size_t size_in_bits, size_t pointer_size_bytes) {
2357 size_t store_size_bytes = get_store_size_bytes(size_in_bits);
2358 if (store_size_bytes >= pointer_size_bytes)
2359 return pointer_size_bytes;
2360 return round_to_next_power_of_2(store_size_bytes);
2361}
2362
2363static size_t get_abi_size_bytes(size_t size_in_bits, size_t pointer_size_bytes) {
2364 size_t store_size_bytes = get_store_size_bytes(size_in_bits);
2365 size_t abi_align = get_abi_align_bytes(size_in_bits, pointer_size_bytes);
2366 return align_forward(store_size_bytes, abi_align);
2367}
2368
2369ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field) {
2370 Error err;
2371 if (struct_field->type_entry == nullptr) {
2372 if ((err = ir_resolve_lazy(g, struct_field->decl_node, struct_field->type_val))) {
2373 return nullptr;
2374 }
2375 struct_field->type_entry = struct_field->type_val->data.x_type;
2376 }
2377 return struct_field->type_entry;
2378}
2379
2380static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
2381 assert(struct_type->id == ZigTypeIdStruct);
2382
2383 Error err;
2384
2385 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
2386 return ErrorSemanticAnalyzeFail;
2387 if (struct_type->data.structure.resolve_status >= ResolveStatusSizeKnown)
2388 return ErrorNone;
2389
2390 if ((err = resolve_struct_alignment(g, struct_type)))
2391 return err;
2392
2393 AstNode *decl_node = struct_type->data.structure.decl_node;
2394
2395 if (struct_type->data.structure.resolve_loop_flag_other) {
2396 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
2397 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2398 add_node_error(g, decl_node,
2399 buf_sprintf("struct '%s' depends on itself", buf_ptr(&struct_type->name)));
2400 }
2401 return ErrorSemanticAnalyzeFail;
2402 }
2403
2404 assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0);
2405
2406 size_t field_count = struct_type->data.structure.src_field_count;
2407
2408 bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
2409 struct_type->data.structure.resolve_loop_flag_other = true;
2410
2411 uint32_t *host_int_bytes = packed ? heap::c_allocator.allocate<uint32_t>(struct_type->data.structure.gen_field_count) : nullptr;
2412
2413 size_t packed_bits_offset = 0;
2414 size_t next_offset = 0;
2415 size_t first_packed_bits_offset_misalign = SIZE_MAX;
2416 size_t gen_field_index = 0;
2417 size_t size_in_bits = 0;
2418 size_t abi_align = struct_type->abi_align;
2419
2420 TypeStructField *last_packed_field = nullptr;
2421
2422 // Calculate offsets
2423 for (size_t i = 0; i < field_count; i += 1) {
2424 TypeStructField *field = struct_type->data.structure.fields[i];
2425 if (field->gen_index == SIZE_MAX)
2426 continue;
2427
2428 field->gen_index = gen_field_index;
2429 field->offset = next_offset;
2430
2431 if (packed) {
2432 ZigType *field_type = resolve_struct_field_type(g, field);
2433 if (field_type == nullptr) {
2434 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2435 return ErrorSemanticAnalyzeFail;
2436 }
2437 if ((err = type_resolve(g, field->type_entry, ResolveStatusSizeKnown))) {
2438 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2439 return err;
2440 }
2441 if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field->type_entry, field->decl_node))) {
2442 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2443 return err;
2444 }
2445
2446 last_packed_field = field;
2447 size_t field_size_in_bits = type_size_bits(g, field_type);
2448 size_t next_packed_bits_offset = packed_bits_offset + field_size_in_bits;
2449
2450 size_in_bits += field_size_in_bits;
2451
2452 if (first_packed_bits_offset_misalign != SIZE_MAX) {
2453 // this field is not byte-aligned; it is part of the previous field with a bit offset
2454 field->bit_offset_in_host = packed_bits_offset - first_packed_bits_offset_misalign;
2455
2456 size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign;
2457 size_t full_abi_size = get_abi_size_bytes(full_bit_count, g->pointer_size_bytes);
2458 if (full_abi_size * 8 == full_bit_count) {
2459 // next field recovers ABI alignment
2460 host_int_bytes[gen_field_index] = full_abi_size;
2461 gen_field_index += 1;
2462 // TODO: https://github.com/ziglang/zig/issues/1512
2463 next_offset = next_field_offset(next_offset, abi_align, full_abi_size, 1);
2464 size_in_bits = next_offset * 8;
2465
2466 first_packed_bits_offset_misalign = SIZE_MAX;
2467 }
2468 } else if (get_abi_size_bytes(field_type->size_in_bits, g->pointer_size_bytes) * 8 != field_size_in_bits) {
2469 first_packed_bits_offset_misalign = packed_bits_offset;
2470 field->bit_offset_in_host = 0;
2471 } else {
2472 // This is a byte-aligned field (both start and end) in a packed struct.
2473 host_int_bytes[gen_field_index] = field_type->size_in_bits / 8;
2474 field->bit_offset_in_host = 0;
2475 gen_field_index += 1;
2476 // TODO: https://github.com/ziglang/zig/issues/1512
2477 next_offset = next_field_offset(next_offset, abi_align, field_type->size_in_bits / 8, 1);
2478 size_in_bits = next_offset * 8;
2479 }
2480 packed_bits_offset = next_packed_bits_offset;
2481 } else {
2482 size_t field_abi_size;
2483 size_t field_size_in_bits;
2484 if ((err = type_val_resolve_abi_size(g, field->decl_node, field->type_val,
2485 &field_abi_size, &field_size_in_bits)))
2486 {
2487 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2488 return err;
2489 }
2490
2491 gen_field_index += 1;
2492 size_t next_src_field_index = i + 1;
2493 for (; next_src_field_index < field_count; next_src_field_index += 1) {
2494 if (struct_type->data.structure.fields[next_src_field_index]->gen_index != SIZE_MAX) {
2495 break;
2496 }
2497 }
2498 size_t next_align = (next_src_field_index == field_count) ?
2499 abi_align : struct_type->data.structure.fields[next_src_field_index]->align;
2500 next_offset = next_field_offset(next_offset, abi_align, field_abi_size, next_align);
2501 size_in_bits = next_offset * 8;
2502 }
2503 }
2504 if (first_packed_bits_offset_misalign != SIZE_MAX) {
2505 size_t full_bit_count = packed_bits_offset - first_packed_bits_offset_misalign;
2506 size_t full_abi_size = get_abi_size_bytes(full_bit_count, 1);
2507 next_offset = next_field_offset(next_offset, abi_align, full_abi_size, abi_align);
2508 ZigType* last_field_type = last_packed_field->type_entry;
2509 // If only last field is misaligned and it is of int type save it so we can generate proper code for it later
2510 if (last_field_type->size_in_bits == full_bit_count && (last_field_type->id == ZigTypeIdInt || last_field_type->id == ZigTypeIdEnum)) {
2511 struct_type->data.structure.misaligned_field = last_packed_field;
2512 }
2513 host_int_bytes[gen_field_index] = full_abi_size;
2514 gen_field_index += 1;
2515 }
2516
2517 struct_type->abi_size = next_offset;
2518 struct_type->size_in_bits = size_in_bits;
2519 struct_type->data.structure.resolve_status = ResolveStatusSizeKnown;
2520 struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index;
2521 struct_type->data.structure.resolve_loop_flag_other = false;
2522 struct_type->data.structure.host_int_bytes = host_int_bytes;
2523
2524
2525 // Resolve types for fields
2526 for (size_t i = 0; i < field_count; i += 1) {
2527 TypeStructField *field = struct_type->data.structure.fields[i];
2528 ZigType *field_type = resolve_struct_field_type(g, field);
2529 if (field_type == nullptr) {
2530 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2531 return ErrorSemanticAnalyzeFail;
2532 }
2533
2534 if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) {
2535 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2536 return err;
2537 }
2538
2539 if (struct_type->data.structure.layout == ContainerLayoutExtern) {
2540 bool ok_type;
2541 if ((err = type_allowed_in_extern(g, field_type, ExternPositionOther, &ok_type))) {
2542 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2543 return ErrorSemanticAnalyzeFail;
2544 }
2545 if (!ok_type) {
2546 add_node_error(g, field->decl_node,
2547 buf_sprintf("extern structs cannot contain fields of type '%s'",
2548 buf_ptr(&field_type->name)));
2549 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2550 return ErrorSemanticAnalyzeFail;
2551 }
2552 }
2553 }
2554
2555 return ErrorNone;
2556}
2557
2558static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
2559 assert(union_type->id == ZigTypeIdUnion);
2560
2561 Error err;
2562
2563 if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)
2564 return ErrorSemanticAnalyzeFail;
2565 if (union_type->data.unionation.resolve_status >= ResolveStatusAlignmentKnown)
2566 return ErrorNone;
2567 if ((err = resolve_union_zero_bits(g, union_type)))
2568 return err;
2569 if (union_type->data.unionation.resolve_status >= ResolveStatusAlignmentKnown)
2570 return ErrorNone;
2571
2572 AstNode *decl_node = union_type->data.structure.decl_node;
2573
2574 if (union_type->data.unionation.resolve_loop_flag_other) {
2575 if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) {
2576 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2577 add_node_error(g, decl_node,
2578 buf_sprintf("union '%s' depends on itself", buf_ptr(&union_type->name)));
2579 }
2580 return ErrorSemanticAnalyzeFail;
2581 }
2582
2583 // set temporary flag
2584 union_type->data.unionation.resolve_loop_flag_other = true;
2585
2586 TypeUnionField *most_aligned_union_member = nullptr;
2587 uint32_t field_count = union_type->data.unionation.src_field_count;
2588 bool packed = union_type->data.unionation.layout == ContainerLayoutPacked;
2589
2590 for (uint32_t i = 0; i < field_count; i += 1) {
2591 TypeUnionField *field = &union_type->data.unionation.fields[i];
2592 if (field->gen_index == UINT32_MAX)
2593 continue;
2594
2595 AstNode *align_expr = nullptr;
2596 if (union_type->data.unionation.decl_node->type == NodeTypeContainerDecl) {
2597 align_expr = field->decl_node->data.struct_field.align_expr;
2598 }
2599 if (align_expr != nullptr) {
2600 if (!analyze_const_align(g, &union_type->data.unionation.decls_scope->base, align_expr,
2601 &field->align))
2602 {
2603 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2604 return ErrorSemanticAnalyzeFail;
2605 }
2606 add_node_error(g, field->decl_node,
2607 buf_create_from_str("TODO implement field alignment syntax for unions. https://github.com/ziglang/zig/issues/3125"));
2608 } else if (packed) {
2609 field->align = 1;
2610 } else if (field->type_entry != nullptr) {
2611 if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
2612 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2613 return err;
2614 }
2615 field->align = field->type_entry->abi_align;
2616 } else {
2617 if ((err = type_val_resolve_abi_align(g, field->decl_node, field->type_val, &field->align))) {
2618 if (g->trace_err != nullptr) {
2619 g->trace_err = add_error_note(g, g->trace_err, field->decl_node,
2620 buf_create_from_str("while checking this field"));
2621 }
2622 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2623 return err;
2624 }
2625 if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)
2626 return ErrorSemanticAnalyzeFail;
2627 }
2628
2629 if (most_aligned_union_member == nullptr || field->align > most_aligned_union_member->align) {
2630 most_aligned_union_member = field;
2631 }
2632 }
2633
2634 // unset temporary flag
2635 union_type->data.unionation.resolve_loop_flag_other = false;
2636 union_type->data.unionation.resolve_status = ResolveStatusAlignmentKnown;
2637 union_type->data.unionation.most_aligned_union_member = most_aligned_union_member;
2638
2639 ZigType *tag_type = union_type->data.unionation.tag_type;
2640 if (tag_type != nullptr && type_has_bits(g, tag_type)) {
2641 if ((err = type_resolve(g, tag_type, ResolveStatusAlignmentKnown))) {
2642 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2643 return ErrorSemanticAnalyzeFail;
2644 }
2645 if (most_aligned_union_member == nullptr) {
2646 union_type->abi_align = tag_type->abi_align;
2647 union_type->data.unionation.gen_tag_index = SIZE_MAX;
2648 union_type->data.unionation.gen_union_index = SIZE_MAX;
2649 } else if (tag_type->abi_align > most_aligned_union_member->align) {
2650 union_type->abi_align = tag_type->abi_align;
2651 union_type->data.unionation.gen_tag_index = 0;
2652 union_type->data.unionation.gen_union_index = 1;
2653 } else {
2654 union_type->abi_align = most_aligned_union_member->align;
2655 union_type->data.unionation.gen_union_index = 0;
2656 union_type->data.unionation.gen_tag_index = 1;
2657 }
2658 } else {
2659 union_type->abi_align = most_aligned_union_member?
2660 most_aligned_union_member->align : 0;
2661 union_type->data.unionation.gen_union_index = SIZE_MAX;
2662 union_type->data.unionation.gen_tag_index = SIZE_MAX;
2663 }
2664
2665 return ErrorNone;
2666}
2667
2668ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field) {
2669 Error err;
2670 if (union_field->type_entry == nullptr) {
2671 if ((err = ir_resolve_lazy(g, union_field->decl_node, union_field->type_val))) {
2672 return nullptr;
2673 }
2674 union_field->type_entry = union_field->type_val->data.x_type;
2675 }
2676 return union_field->type_entry;
2677}
2678
2679static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
2680 assert(union_type->id == ZigTypeIdUnion);
2681
2682 Error err;
2683
2684 if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)
2685 return ErrorSemanticAnalyzeFail;
2686 if (union_type->data.unionation.resolve_status >= ResolveStatusSizeKnown)
2687 return ErrorNone;
2688
2689 if ((err = resolve_union_alignment(g, union_type)))
2690 return err;
2691
2692 AstNode *decl_node = union_type->data.unionation.decl_node;
2693
2694 uint32_t field_count = union_type->data.unionation.src_field_count;
2695 TypeUnionField *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;
2696
2697 assert(union_type->data.unionation.fields);
2698
2699 size_t union_abi_size = 0;
2700 size_t union_size_in_bits = 0;
2701
2702 if (union_type->data.unionation.resolve_loop_flag_other) {
2703 if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) {
2704 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2705 add_node_error(g, decl_node,
2706 buf_sprintf("union '%s' depends on itself", buf_ptr(&union_type->name)));
2707 }
2708 return ErrorSemanticAnalyzeFail;
2709 }
2710
2711 // set temporary flag
2712 union_type->data.unionation.resolve_loop_flag_other = true;
2713
2714 const bool is_packed = union_type->data.unionation.layout == ContainerLayoutPacked;
2715
2716 for (uint32_t i = 0; i < field_count; i += 1) {
2717 TypeUnionField *union_field = &union_type->data.unionation.fields[i];
2718 ZigType *field_type = resolve_union_field_type(g, union_field);
2719 if (field_type == nullptr) {
2720 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2721 return ErrorSemanticAnalyzeFail;
2722 }
2723
2724 if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) {
2725 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2726 return ErrorSemanticAnalyzeFail;
2727 }
2728
2729 if (is_packed) {
2730 if ((err = emit_error_unless_type_allowed_in_packed_union(g, field_type, union_field->decl_node))) {
2731 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2732 return err;
2733 }
2734 }
2735
2736 if (type_is_invalid(union_type))
2737 return ErrorSemanticAnalyzeFail;
2738
2739 if (!type_has_bits(g, field_type))
2740 continue;
2741
2742 union_abi_size = max(union_abi_size, field_type->abi_size);
2743 union_size_in_bits = max(union_size_in_bits, field_type->size_in_bits);
2744 }
2745
2746 // The union itself for now has to be treated as being independently aligned.
2747 // See https://github.com/ziglang/zig/issues/2166.
2748 if (most_aligned_union_member != nullptr) {
2749 union_abi_size = align_forward(union_abi_size, most_aligned_union_member->align);
2750 }
2751
2752 // unset temporary flag
2753 union_type->data.unionation.resolve_loop_flag_other = false;
2754 union_type->data.unionation.resolve_status = ResolveStatusSizeKnown;
2755 union_type->data.unionation.union_abi_size = union_abi_size;
2756
2757 ZigType *tag_type = union_type->data.unionation.tag_type;
2758 if (tag_type != nullptr && type_has_bits(g, tag_type)) {
2759 if ((err = type_resolve(g, tag_type, ResolveStatusSizeKnown))) {
2760 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2761 return ErrorSemanticAnalyzeFail;
2762 }
2763 if (most_aligned_union_member == nullptr) {
2764 union_type->abi_size = tag_type->abi_size;
2765 union_type->size_in_bits = tag_type->size_in_bits;
2766 } else {
2767 size_t field_sizes[2];
2768 size_t field_aligns[2];
2769 field_sizes[union_type->data.unionation.gen_tag_index] = tag_type->abi_size;
2770 field_aligns[union_type->data.unionation.gen_tag_index] = tag_type->abi_align;
2771 field_sizes[union_type->data.unionation.gen_union_index] = union_abi_size;
2772 field_aligns[union_type->data.unionation.gen_union_index] = most_aligned_union_member->align;
2773 size_t field2_offset = next_field_offset(0, union_type->abi_align, field_sizes[0], field_aligns[1]);
2774 union_type->abi_size = next_field_offset(field2_offset, union_type->abi_align, field_sizes[1], union_type->abi_align);
2775 union_type->size_in_bits = union_type->abi_size * 8;
2776 }
2777 } else {
2778 union_type->abi_size = union_abi_size;
2779 union_type->size_in_bits = union_size_in_bits;
2780 }
2781
2782 return ErrorNone;
2783}
2784
2785static Error type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty, bool *result) {
2786 // Only integer types are allowed by the C ABI
2787 if(ty->id != ZigTypeIdInt) {
2788 *result = false;
2789 return ErrorNone;
2790 }
2791
2792 // According to the ANSI C standard the enumeration type should be either a
2793 // signed char, a signed integer or an unsigned one. But GCC/Clang allow
2794 // other integral types as a compiler extension so let's accommodate them
2795 // aswell.
2796 return type_allowed_in_extern(g, ty, ExternPositionOther, result);
2797}
2798
2799static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2800 Error err;
2801 assert(enum_type->id == ZigTypeIdEnum);
2802
2803 if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid)
2804 return ErrorSemanticAnalyzeFail;
2805 if (enum_type->data.enumeration.resolve_status >= ResolveStatusZeroBitsKnown)
2806 return ErrorNone;
2807
2808 AstNode *decl_node = enum_type->data.enumeration.decl_node;
2809
2810 if (enum_type->data.enumeration.resolve_loop_flag) {
2811 if (enum_type->data.enumeration.resolve_status != ResolveStatusInvalid) {
2812 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2813 add_node_error(g, decl_node,
2814 buf_sprintf("enum '%s' depends on itself",
2815 buf_ptr(&enum_type->name)));
2816 }
2817 return ErrorSemanticAnalyzeFail;
2818 }
2819
2820 enum_type->data.enumeration.resolve_loop_flag = true;
2821
2822 uint32_t field_count;
2823 if (decl_node->type == NodeTypeContainerDecl) {
2824 assert(!enum_type->data.enumeration.fields);
2825 field_count = (uint32_t)decl_node->data.container_decl.fields.length;
2826 } else {
2827 field_count = enum_type->data.enumeration.src_field_count + enum_type->data.enumeration.non_exhaustive;
2828 }
2829
2830 if (field_count == 0) {
2831 add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
2832 enum_type->data.enumeration.src_field_count = field_count;
2833 enum_type->data.enumeration.fields = nullptr;
2834 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2835 return ErrorSemanticAnalyzeFail;
2836 }
2837
2838 Scope *scope = &enum_type->data.enumeration.decls_scope->base;
2839
2840 ZigType *tag_int_type;
2841 if (enum_type->data.enumeration.layout == ContainerLayoutExtern) {
2842 tag_int_type = get_c_int_type(g, CIntTypeInt);
2843 } else {
2844 tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
2845 }
2846
2847 enum_type->size_in_bits = tag_int_type->size_in_bits;
2848 enum_type->abi_size = tag_int_type->abi_size;
2849 enum_type->abi_align = tag_int_type->abi_align;
2850
2851 ZigType *wanted_tag_int_type = nullptr;
2852 if (decl_node->type == NodeTypeContainerDecl) {
2853 if (decl_node->data.container_decl.init_arg_expr != nullptr) {
2854 wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
2855 enum_type->data.enumeration.has_explicit_tag_type = true;
2856 }
2857 } else {
2858 wanted_tag_int_type = enum_type->data.enumeration.tag_int_type;
2859 enum_type->data.enumeration.has_explicit_tag_type = true;
2860 }
2861
2862 if (wanted_tag_int_type != nullptr) {
2863 if (type_is_invalid(wanted_tag_int_type)) {
2864 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2865 } else if (wanted_tag_int_type->id != ZigTypeIdInt &&
2866 wanted_tag_int_type->id != ZigTypeIdComptimeInt) {
2867 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2868 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
2869 buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
2870 } else {
2871 if (enum_type->data.enumeration.layout == ContainerLayoutExtern) {
2872 bool ok_type;
2873 if ((err = type_is_valid_extern_enum_tag(g, wanted_tag_int_type, &ok_type))) {
2874 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2875 return err;
2876 }
2877 if (!ok_type) {
2878 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2879 ErrorMsg *msg = add_node_error(g, decl_node->data.container_decl.init_arg_expr,
2880 buf_sprintf("'%s' is not a valid tag type for an extern enum",
2881 buf_ptr(&wanted_tag_int_type->name)));
2882 add_error_note(g, msg, decl_node->data.container_decl.init_arg_expr,
2883 buf_sprintf("any integral type of size 8, 16, 32, 64 or 128 bit is valid"));
2884 return ErrorSemanticAnalyzeFail;
2885 }
2886 }
2887 tag_int_type = wanted_tag_int_type;
2888 }
2889 }
2890
2891 enum_type->data.enumeration.tag_int_type = tag_int_type;
2892 enum_type->size_in_bits = tag_int_type->size_in_bits;
2893 enum_type->abi_size = tag_int_type->abi_size;
2894 enum_type->abi_align = tag_int_type->abi_align;
2895
2896 BigInt bi_one;
2897 bigint_init_unsigned(&bi_one, 1);
2898
2899 if (decl_node->type == NodeTypeContainerDecl) {
2900 AstNode *last_field_node = decl_node->data.container_decl.fields.at(field_count - 1);
2901 if (buf_eql_str(last_field_node->data.struct_field.name, "_")) {
2902 if (last_field_node->data.struct_field.value != nullptr) {
2903 add_node_error(g, last_field_node, buf_sprintf("value assigned to '_' field of non-exhaustive enum"));
2904 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2905 }
2906 if (decl_node->data.container_decl.init_arg_expr == nullptr) {
2907 add_node_error(g, decl_node, buf_sprintf("non-exhaustive enum must specify size"));
2908 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2909 }
2910 enum_type->data.enumeration.non_exhaustive = true;
2911 } else {
2912 enum_type->data.enumeration.non_exhaustive = false;
2913 }
2914 }
2915
2916 if (enum_type->data.enumeration.non_exhaustive) {
2917 field_count -= 1;
2918 if (field_count > 1 && log2_u64(field_count) == enum_type->size_in_bits) {
2919 add_node_error(g, decl_node, buf_sprintf("non-exhaustive enum specifies every value"));
2920 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2921 }
2922 }
2923
2924 if (decl_node->type == NodeTypeContainerDecl) {
2925 enum_type->data.enumeration.src_field_count = field_count;
2926 enum_type->data.enumeration.fields = heap::c_allocator.allocate<TypeEnumField>(field_count);
2927 enum_type->data.enumeration.fields_by_name.init(field_count);
2928
2929 HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};
2930 occupied_tag_values.init(field_count);
2931
2932 TypeEnumField *last_enum_field = nullptr;
2933
2934 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
2935 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
2936 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
2937 type_enum_field->name = field_node->data.struct_field.name;
2938 type_enum_field->decl_index = field_i;
2939 type_enum_field->decl_node = field_node;
2940
2941 if (field_node->data.struct_field.type != nullptr) {
2942 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.type,
2943 buf_sprintf("structs and unions, not enums, support field types"));
2944 add_error_note(g, msg, decl_node,
2945 buf_sprintf("consider 'union(enum)' here"));
2946 } else if (field_node->data.struct_field.align_expr != nullptr) {
2947 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.align_expr,
2948 buf_sprintf("structs and unions, not enums, support field alignment"));
2949 add_error_note(g, msg, decl_node,
2950 buf_sprintf("consider 'union(enum)' here"));
2951 }
2952
2953 if (buf_eql_str(type_enum_field->name, "_")) {
2954 add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last"));
2955 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2956 }
2957
2958 auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field);
2959 if (field_entry != nullptr) {
2960 ErrorMsg *msg = add_node_error(g, field_node,
2961 buf_sprintf("duplicate enum field: '%s'", buf_ptr(type_enum_field->name)));
2962 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
2963 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2964 continue;
2965 }
2966
2967 AstNode *tag_value = field_node->data.struct_field.value;
2968
2969 if (tag_value != nullptr) {
2970 // A user-specified value is available
2971 ZigValue *result = analyze_const_value(g, scope, tag_value, tag_int_type,
2972 nullptr, UndefBad);
2973 if (type_is_invalid(result->type)) {
2974 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2975 continue;
2976 }
2977
2978 assert(result->special != ConstValSpecialRuntime);
2979 assert(result->type->id == ZigTypeIdInt || result->type->id == ZigTypeIdComptimeInt);
2980
2981 bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
2982 } else {
2983 // No value was explicitly specified: allocate the last value + 1
2984 // or, if this is the first element, zero
2985 if (last_enum_field != nullptr) {
2986 bigint_add(&type_enum_field->value, &last_enum_field->value, &bi_one);
2987 } else {
2988 bigint_init_unsigned(&type_enum_field->value, 0);
2989 }
2990
2991 // Make sure we can represent this number with tag_int_type
2992 if (!bigint_fits_in_bits(&type_enum_field->value,
2993 tag_int_type->size_in_bits,
2994 tag_int_type->data.integral.is_signed)) {
2995 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2996
2997 Buf *val_buf = buf_alloc();
2998 bigint_append_buf(val_buf, &type_enum_field->value, 10);
2999 add_node_error(g, field_node,
3000 buf_sprintf("enumeration value %s too large for type '%s'",
3001 buf_ptr(val_buf), buf_ptr(&tag_int_type->name)));
3002
3003 break;
3004 }
3005 }
3006
3007 // Make sure the value is unique
3008 auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);
3009 if (entry != nullptr && enum_type->data.enumeration.layout != ContainerLayoutExtern) {
3010 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
3011
3012 Buf *val_buf = buf_alloc();
3013 bigint_append_buf(val_buf, &type_enum_field->value, 10);
3014
3015 ErrorMsg *msg = add_node_error(g, field_node,
3016 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
3017 add_error_note(g, msg, entry->value,
3018 buf_sprintf("other occurrence here"));
3019 }
3020
3021 last_enum_field = type_enum_field;
3022 }
3023 occupied_tag_values.deinit();
3024 }
3025
3026 if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid)
3027 return ErrorSemanticAnalyzeFail;
3028
3029 enum_type->data.enumeration.resolve_loop_flag = false;
3030 enum_type->data.enumeration.resolve_status = ResolveStatusSizeKnown;
3031
3032 return ErrorNone;
3033}
3034
3035static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
3036 assert(struct_type->id == ZigTypeIdStruct);
3037
3038 Error err;
3039
3040 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
3041 return ErrorSemanticAnalyzeFail;
3042 if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown)
3043 return ErrorNone;
3044
3045 AstNode *decl_node = struct_type->data.structure.decl_node;
3046
3047 if (decl_node->data.container_decl.unsupported_explicit_backing_int) {
3048 add_node_error(g, decl_node, buf_create_from_str(
3049 "the stage1 compiler does not support explicit backing integer types on packed structs"));
3050 return ErrorSemanticAnalyzeFail;
3051 }
3052
3053 if (struct_type->data.structure.resolve_loop_flag_zero_bits) {
3054 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
3055 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
3056 add_node_error(g, decl_node,
3057 buf_sprintf("struct '%s' depends on itself",
3058 buf_ptr(&struct_type->name)));
3059 }
3060 return ErrorSemanticAnalyzeFail;
3061 }
3062 struct_type->data.structure.resolve_loop_flag_zero_bits = true;
3063
3064 size_t field_count;
3065 if (decl_node->type == NodeTypeContainerDecl) {
3066 field_count = decl_node->data.container_decl.fields.length;
3067 struct_type->data.structure.src_field_count = (uint32_t)field_count;
3068
3069 src_assert(struct_type->data.structure.fields == nullptr, decl_node);
3070 struct_type->data.structure.fields = alloc_type_struct_fields(field_count);
3071 } else if (is_anon_container(struct_type) || struct_type->data.structure.created_by_at_type) {
3072 field_count = struct_type->data.structure.src_field_count;
3073
3074 src_assert(field_count == 0 || struct_type->data.structure.fields != nullptr, decl_node);
3075 } else zig_unreachable();
3076
3077 struct_type->data.structure.fields_by_name.init(field_count);
3078
3079 Scope *scope = &struct_type->data.structure.decls_scope->base;
3080
3081 size_t gen_field_index = 0;
3082 for (size_t i = 0; i < field_count; i += 1) {
3083 TypeStructField *type_struct_field = struct_type->data.structure.fields[i];
3084
3085 AstNode *field_node;
3086 if (decl_node->type == NodeTypeContainerDecl) {
3087 field_node = decl_node->data.container_decl.fields.at(i);
3088 type_struct_field->name = field_node->data.struct_field.name;
3089 type_struct_field->decl_node = field_node;
3090 if (field_node->data.struct_field.comptime_token != 0) {
3091 if (field_node->data.struct_field.value == nullptr) {
3092 add_token_error(g, field_node->owner,
3093 field_node->data.struct_field.comptime_token,
3094 buf_sprintf("comptime struct field missing initialization value"));
3095 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
3096 return ErrorSemanticAnalyzeFail;
3097 }
3098 type_struct_field->is_comptime = true;
3099 }
3100
3101 if (field_node->data.struct_field.type == nullptr) {
3102 add_node_error(g, field_node, buf_sprintf("struct field missing type"));
3103 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
3104 return ErrorSemanticAnalyzeFail;
3105 }
3106 } else if (is_anon_container(struct_type) || struct_type->data.structure.created_by_at_type) {
3107 field_node = type_struct_field->decl_node;
3108
3109 src_assert(type_struct_field->type_entry != nullptr, field_node);
3110 } else zig_unreachable();
3111
3112 auto field_entry = struct_type->data.structure.fields_by_name.put_unique(type_struct_field->name, type_struct_field);
3113 if (field_entry != nullptr) {
3114 ErrorMsg *msg = add_node_error(g, field_node,
3115 buf_sprintf("duplicate struct field: '%s'", buf_ptr(type_struct_field->name)));
3116 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
3117 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
3118 return ErrorSemanticAnalyzeFail;
3119 }
3120
3121 ZigValue *field_type_val;
3122 if (decl_node->type == NodeTypeContainerDecl) {
3123 field_type_val = analyze_const_value(g, scope,
3124 field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);
3125 if (type_is_invalid(field_type_val->type)) {
3126 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
3127 return ErrorSemanticAnalyzeFail;
3128 }
3129 assert(field_type_val->special != ConstValSpecialRuntime);
3130 type_struct_field->type_val = field_type_val;
3131 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
3132 return ErrorSemanticAnalyzeFail;
3133 } else if (is_anon_container(struct_type) || struct_type->data.structure.created_by_at_type) {
3134 field_type_val = type_struct_field->type_val;
3135 } else zig_unreachable();
3136
3137 bool field_is_opaque_type;
3138 if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) {
3139 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
3140 return ErrorSemanticAnalyzeFail;
3141 }
3142 if (field_is_opaque_type) {
3143 add_node_error(g, field_node,
3144 buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));
3145 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
3146 return ErrorSemanticAnalyzeFail;
3147 }
3148
3149 type_struct_field->src_index = i;
3150 type_struct_field->gen_index = SIZE_MAX;
3151
3152 if (type_struct_field->is_comptime)
3153 continue;
3154
3155 switch (type_val_resolve_requires_comptime(g, field_type_val)) {
3156 case ReqCompTimeYes:
3157 struct_type->data.structure.requires_comptime = true;
3158 break;
3159 case ReqCompTimeInvalid:
3160 if (g->trace_err != nullptr) {
3161 g->trace_err = add_error_note(g, g->trace_err, field_node,
3162 buf_create_from_str("while checking this field"));
3163 }
3164 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
3165 return ErrorSemanticAnalyzeFail;
3166 case ReqCompTimeNo:
3167 break;
3168 }
3169
3170 bool field_is_zero_bits;
3171 if ((err = type_val_resolve_zero_bits(g, field_type_val, struct_type, nullptr, &field_is_zero_bits))) {
3172 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
3173 return ErrorSemanticAnalyzeFail;
3174 }
3175 if (field_is_zero_bits)
3176 continue;
3177
3178 type_struct_field->gen_index = gen_field_index;
3179 gen_field_index += 1;
3180 }
3181
3182 struct_type->data.structure.resolve_loop_flag_zero_bits = false;
3183 struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index;
3184 if (gen_field_index != 0) {
3185 struct_type->abi_size = SIZE_MAX;
3186 struct_type->size_in_bits = SIZE_MAX;
3187 }
3188
3189 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
3190 return ErrorSemanticAnalyzeFail;
3191
3192 struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown;
3193 return ErrorNone;
3194}
3195
3196static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
3197 assert(struct_type->id == ZigTypeIdStruct);
3198
3199 Error err;
3200
3201 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
3202 return ErrorSemanticAnalyzeFail;
3203 if (struct_type->data.structure.resolve_status >= ResolveStatusAlignmentKnown)
3204 return ErrorNone;
3205 if ((err = resolve_struct_zero_bits(g, struct_type)))
3206 return err;
3207 if (struct_type->data.structure.resolve_status >= ResolveStatusAlignmentKnown)
3208 return ErrorNone;
3209
3210 AstNode *decl_node = struct_type->data.structure.decl_node;
3211
3212 if (struct_type->data.structure.resolve_loop_flag_other) {
3213 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
3214 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
3215 add_node_error(g, decl_node,
3216 buf_sprintf("struct '%s' depends on itself", buf_ptr(&struct_type->name)));
3217 }
3218 return ErrorSemanticAnalyzeFail;
3219 }
3220
3221 struct_type->data.structure.resolve_loop_flag_other = true;
3222
3223 size_t field_count = struct_type->data.structure.src_field_count;
3224 bool packed = struct_type->data.structure.layout == ContainerLayoutPacked;
3225
3226 for (size_t i = 0; i < field_count; i += 1) {
3227 TypeStructField *field = struct_type->data.structure.fields[i];
3228 if (field->gen_index == SIZE_MAX)
3229 continue;
3230
3231 AstNode *align_expr = (field->decl_node->type == NodeTypeStructField) ?
3232 field->decl_node->data.struct_field.align_expr : nullptr;
3233 if (align_expr != nullptr) {
3234 if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr,
3235 &field->align))
3236 {
3237 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
3238 return ErrorSemanticAnalyzeFail;
3239 }
3240 } else if (packed) {
3241 field->align = 1;
3242 } else {
3243 if ((err = type_val_resolve_abi_align(g, field->decl_node, field->type_val, &field->align))) {
3244 if (g->trace_err != nullptr) {
3245 g->trace_err = add_error_note(g, g->trace_err, field->decl_node,
3246 buf_create_from_str("while checking this field"));
3247 }
3248 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
3249 return err;
3250 }
3251 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
3252 return ErrorSemanticAnalyzeFail;
3253 }
3254
3255 if (field->align > struct_type->abi_align) {
3256 struct_type->abi_align = field->align;
3257 }
3258 }
3259
3260 if (!type_has_bits(g, struct_type)) {
3261 assert(struct_type->abi_align == 0);
3262 }
3263
3264 struct_type->data.structure.resolve_loop_flag_other = false;
3265
3266 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) {
3267 return ErrorSemanticAnalyzeFail;
3268 }
3269
3270 struct_type->data.structure.resolve_status = ResolveStatusAlignmentKnown;
3271 return ErrorNone;
3272}
3273
3274static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
3275 assert(union_type->id == ZigTypeIdUnion);
3276
3277 Error err;
3278
3279 if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)
3280 return ErrorSemanticAnalyzeFail;
3281
3282 if (union_type->data.unionation.resolve_status >= ResolveStatusZeroBitsKnown)
3283 return ErrorNone;
3284
3285 AstNode *decl_node = union_type->data.unionation.decl_node;
3286
3287 if (union_type->data.unionation.resolve_loop_flag_zero_bits) {
3288 if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) {
3289 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3290 add_node_error(g, decl_node,
3291 buf_sprintf("union '%s' depends on itself",
3292 buf_ptr(&union_type->name)));
3293 }
3294 return ErrorSemanticAnalyzeFail;
3295 }
3296
3297 union_type->data.unionation.resolve_loop_flag_zero_bits = true;
3298
3299 uint32_t field_count;
3300 if (decl_node->type == NodeTypeContainerDecl) {
3301 assert(union_type->data.unionation.fields == nullptr);
3302 field_count = (uint32_t)decl_node->data.container_decl.fields.length;
3303 union_type->data.unionation.src_field_count = field_count;
3304 union_type->data.unionation.fields = heap::c_allocator.allocate<TypeUnionField>(field_count);
3305 union_type->data.unionation.fields_by_name.init(field_count);
3306 } else {
3307 field_count = union_type->data.unionation.src_field_count;
3308 assert(field_count == 0 || union_type->data.unionation.fields != nullptr);
3309 }
3310
3311 if (field_count == 0) {
3312 add_node_error(g, decl_node, buf_sprintf("unions must have 1 or more fields"));
3313 union_type->data.unionation.src_field_count = field_count;
3314 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3315 return ErrorSemanticAnalyzeFail;
3316 }
3317
3318 Scope *scope = &union_type->data.unionation.decls_scope->base;
3319
3320 HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};
3321
3322 bool is_auto_enum; // union(enum) or union(enum(expr))
3323 bool is_explicit_enum; // union(expr)
3324 AstNode *enum_type_node; // expr in union(enum(expr)) or union(expr)
3325 if (decl_node->type == NodeTypeContainerDecl) {
3326 is_auto_enum = decl_node->data.container_decl.auto_enum;
3327 is_explicit_enum = decl_node->data.container_decl.init_arg_expr != nullptr;
3328 enum_type_node = decl_node->data.container_decl.init_arg_expr;
3329 } else {
3330 is_auto_enum = false;
3331 is_explicit_enum = union_type->data.unionation.tag_type != nullptr;
3332 enum_type_node = nullptr;
3333 }
3334 union_type->data.unionation.have_explicit_tag_type = is_auto_enum || is_explicit_enum;
3335
3336 bool is_auto_layout = union_type->data.unionation.layout == ContainerLayoutAuto;
3337 bool want_safety = (field_count >= 2)
3338 && (is_auto_layout || is_explicit_enum)
3339 && !(g->build_mode == BuildModeFastRelease || g->build_mode == BuildModeSmallRelease);
3340 ZigType *tag_type;
3341 bool create_enum_type = is_auto_enum || (!is_explicit_enum && want_safety);
3342 bool *covered_enum_fields;
3343 bool *is_zero_bits = heap::c_allocator.allocate<bool>(field_count);
3344 if (create_enum_type) {
3345 occupied_tag_values.init(field_count);
3346
3347 ZigType *tag_int_type;
3348 if (enum_type_node != nullptr) {
3349 tag_int_type = analyze_type_expr(g, scope, enum_type_node);
3350 if (type_is_invalid(tag_int_type)) {
3351 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3352 return ErrorSemanticAnalyzeFail;
3353 }
3354 if (tag_int_type->id != ZigTypeIdInt && tag_int_type->id != ZigTypeIdComptimeInt) {
3355 add_node_error(g, enum_type_node,
3356 buf_sprintf("expected integer tag type, found '%s'", buf_ptr(&tag_int_type->name)));
3357 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3358 return ErrorSemanticAnalyzeFail;
3359 }
3360 if (tag_int_type->id == ZigTypeIdInt) {
3361 BigInt bi;
3362 bigint_init_unsigned(&bi, field_count - 1);
3363 if (!bigint_fits_in_bits(&bi,
3364 tag_int_type->data.integral.bit_count,
3365 tag_int_type->data.integral.is_signed))
3366 {
3367 ErrorMsg *msg = add_node_error(g, enum_type_node,
3368 buf_sprintf("specified integer tag type cannot represent every field"));
3369 add_error_note(g, msg, enum_type_node,
3370 buf_sprintf("type %s cannot fit values in range 0...%" PRIu32,
3371 buf_ptr(&tag_int_type->name), field_count - 1));
3372 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3373 return ErrorSemanticAnalyzeFail;
3374 }
3375 }
3376 } else {
3377 tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
3378 }
3379
3380 tag_type = new_type_table_entry(ZigTypeIdEnum);
3381 buf_resize(&tag_type->name, 0);
3382 buf_appendf(&tag_type->name, "@typeInfo(%s).Union.tag_type.?", buf_ptr(&union_type->name));
3383 tag_type->llvm_type = tag_int_type->llvm_type;
3384 tag_type->llvm_di_type = tag_int_type->llvm_di_type;
3385 tag_type->abi_size = tag_int_type->abi_size;
3386 tag_type->abi_align = tag_int_type->abi_align;
3387 tag_type->size_in_bits = tag_int_type->size_in_bits;
3388
3389 tag_type->data.enumeration.tag_int_type = tag_int_type;
3390 tag_type->data.enumeration.resolve_status = ResolveStatusSizeKnown;
3391 tag_type->data.enumeration.decl_node = decl_node;
3392 tag_type->data.enumeration.layout = ContainerLayoutAuto;
3393 tag_type->data.enumeration.src_field_count = field_count;
3394 tag_type->data.enumeration.fields = heap::c_allocator.allocate<TypeEnumField>(field_count);
3395 tag_type->data.enumeration.fields_by_name.init(field_count);
3396 tag_type->data.enumeration.decls_scope = create_decls_scope(
3397 g, nullptr, nullptr, tag_type, get_scope_import(scope), &tag_type->name);
3398 } else if (enum_type_node != nullptr) {
3399 tag_type = analyze_type_expr(g, scope, enum_type_node);
3400 } else {
3401 if (decl_node->type == NodeTypeContainerDecl) {
3402 tag_type = nullptr;
3403 } else {
3404 tag_type = union_type->data.unionation.tag_type;
3405 }
3406 }
3407 if (tag_type != nullptr) {
3408 if (type_is_invalid(tag_type)) {
3409 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3410 return ErrorSemanticAnalyzeFail;
3411 }
3412 if (tag_type->id != ZigTypeIdEnum) {
3413 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3414 add_node_error(g, enum_type_node != nullptr ? enum_type_node : decl_node,
3415 buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&tag_type->name)));
3416 return ErrorSemanticAnalyzeFail;
3417 }
3418 if ((err = type_resolve(g, tag_type, ResolveStatusAlignmentKnown))) {
3419 assert(g->errors.length != 0);
3420 return err;
3421 }
3422 covered_enum_fields = heap::c_allocator.allocate<bool>(tag_type->data.enumeration.src_field_count);
3423 }
3424 union_type->data.unionation.tag_type = tag_type;
3425
3426 for (uint32_t i = 0; i < field_count; i += 1) {
3427 TypeUnionField *union_field = &union_type->data.unionation.fields[i];
3428 if (decl_node->type == NodeTypeContainerDecl) {
3429 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
3430 union_field->name = field_node->data.struct_field.name;
3431 union_field->decl_node = field_node;
3432 union_field->gen_index = UINT32_MAX;
3433 is_zero_bits[i] = false;
3434
3435 auto field_entry = union_type->data.unionation.fields_by_name.put_unique(union_field->name, union_field);
3436 if (field_entry != nullptr) {
3437 ErrorMsg *msg = add_node_error(g, union_field->decl_node,
3438 buf_sprintf("duplicate union field: '%s'", buf_ptr(union_field->name)));
3439 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
3440 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3441 return ErrorSemanticAnalyzeFail;
3442 }
3443
3444 if (field_node->data.struct_field.type == nullptr) {
3445 if (is_auto_enum || is_explicit_enum) {
3446 union_field->type_entry = g->builtin_types.entry_void;
3447 is_zero_bits[i] = true;
3448 } else {
3449 add_node_error(g, field_node, buf_sprintf("union field missing type"));
3450 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3451 return ErrorSemanticAnalyzeFail;
3452 }
3453 } else {
3454 ZigValue *field_type_val = analyze_const_value(g, scope,
3455 field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);
3456 if (type_is_invalid(field_type_val->type)) {
3457 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3458 return ErrorSemanticAnalyzeFail;
3459 }
3460 assert(field_type_val->special != ConstValSpecialRuntime);
3461 union_field->type_val = field_type_val;
3462 }
3463
3464 if (field_node->data.struct_field.value != nullptr && !is_auto_enum) {
3465 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,
3466 buf_create_from_str("untagged union field assignment"));
3467 add_error_note(g, msg, decl_node, buf_create_from_str("consider 'union(enum)' here"));
3468 }
3469 }
3470
3471 if (union_field->type_val != nullptr) {
3472 bool field_is_opaque_type;
3473 if ((err = type_val_resolve_is_opaque_type(g, union_field->type_val, &field_is_opaque_type))) {
3474 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3475 return ErrorSemanticAnalyzeFail;
3476 }
3477 if (field_is_opaque_type) {
3478 add_node_error(g, union_field->decl_node,
3479 buf_create_from_str(
3480 "opaque types have unknown size and therefore cannot be directly embedded in unions"));
3481 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3482 return ErrorSemanticAnalyzeFail;
3483 }
3484
3485 switch (type_val_resolve_requires_comptime(g, union_field->type_val)) {
3486 case ReqCompTimeInvalid:
3487 if (g->trace_err != nullptr) {
3488 g->trace_err = add_error_note(g, g->trace_err, union_field->decl_node,
3489 buf_create_from_str("while checking this field"));
3490 }
3491 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3492 return ErrorSemanticAnalyzeFail;
3493 case ReqCompTimeYes:
3494 union_type->data.unionation.requires_comptime = true;
3495 break;
3496 case ReqCompTimeNo:
3497 break;
3498 }
3499
3500 if ((err = type_val_resolve_zero_bits(g, union_field->type_val, union_type, nullptr, &is_zero_bits[i]))) {
3501 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3502 return ErrorSemanticAnalyzeFail;
3503 }
3504 }
3505
3506 if (create_enum_type) {
3507 union_field->enum_field = &tag_type->data.enumeration.fields[i];
3508 union_field->enum_field->name = union_field->name;
3509 union_field->enum_field->decl_index = i;
3510 union_field->enum_field->decl_node = union_field->decl_node;
3511
3512 auto prev_entry = tag_type->data.enumeration.fields_by_name.put_unique(union_field->enum_field->name, union_field->enum_field);
3513 assert(prev_entry == nullptr); // caught by union de-duplicator above
3514
3515 AstNode *tag_value = decl_node->type == NodeTypeContainerDecl
3516 ? union_field->decl_node->data.struct_field.value : nullptr;
3517
3518 // In this first pass we resolve explicit tag values.
3519 // In a second pass we will fill in the unspecified ones.
3520 if (tag_value != nullptr) {
3521 ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;
3522 ZigValue *result = analyze_const_value(g, scope, tag_value, tag_int_type,
3523 nullptr, UndefBad);
3524 if (type_is_invalid(result->type)) {
3525 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3526 return ErrorSemanticAnalyzeFail;
3527 }
3528 assert(result->special != ConstValSpecialRuntime);
3529 assert(result->type->id == ZigTypeIdInt);
3530 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
3531 if (entry == nullptr) {
3532 bigint_init_bigint(&union_field->enum_field->value, &result->data.x_bigint);
3533 } else {
3534 Buf *val_buf = buf_alloc();
3535 bigint_append_buf(val_buf, &result->data.x_bigint, 10);
3536
3537 ErrorMsg *msg = add_node_error(g, tag_value,
3538 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
3539 add_error_note(g, msg, entry->value,
3540 buf_sprintf("other occurrence here"));
3541 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3542 return ErrorSemanticAnalyzeFail;
3543 }
3544 }
3545 } else if (tag_type != nullptr) {
3546 union_field->enum_field = find_enum_type_field(tag_type, union_field->name);
3547 if (union_field->enum_field == nullptr) {
3548 ErrorMsg *msg = add_node_error(g, union_field->decl_node,
3549 buf_sprintf("enum field not found: '%s'", buf_ptr(union_field->name)));
3550 add_error_note(g, msg, tag_type->data.enumeration.decl_node,
3551 buf_sprintf("enum declared here"));
3552 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3553 return ErrorSemanticAnalyzeFail;
3554 }
3555 covered_enum_fields[union_field->enum_field->decl_index] = true;
3556 } else {
3557 union_field->enum_field = heap::c_allocator.create<TypeEnumField>();
3558 union_field->enum_field->name = union_field->name;
3559 union_field->enum_field->decl_index = i;
3560 bigint_init_unsigned(&union_field->enum_field->value, i);
3561 }
3562 assert(union_field->enum_field != nullptr);
3563 }
3564
3565 uint32_t gen_field_index = 0;
3566 for (uint32_t i = 0; i < field_count; i += 1) {
3567 TypeUnionField *union_field = &union_type->data.unionation.fields[i];
3568 if (!is_zero_bits[i]) {
3569 union_field->gen_index = gen_field_index;
3570 gen_field_index += 1;
3571 }
3572 }
3573 heap::c_allocator.deallocate(is_zero_bits, field_count);
3574
3575 bool src_have_tag = is_auto_enum || is_explicit_enum;
3576
3577 if (src_have_tag && union_type->data.unionation.layout != ContainerLayoutAuto) {
3578 const char *qual_str;
3579 switch (union_type->data.unionation.layout) {
3580 case ContainerLayoutAuto:
3581 zig_unreachable();
3582 case ContainerLayoutPacked:
3583 qual_str = "packed";
3584 break;
3585 case ContainerLayoutExtern:
3586 qual_str = "extern";
3587 break;
3588 }
3589 AstNode *source_node = enum_type_node != nullptr ? enum_type_node : decl_node;
3590 add_node_error(g, source_node,
3591 buf_sprintf("%s union does not support enum tag type", qual_str));
3592 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3593 return ErrorSemanticAnalyzeFail;
3594 }
3595
3596 if (create_enum_type) {
3597 if (decl_node->type == NodeTypeContainerDecl) {
3598 // Now iterate again and populate the unspecified tag values
3599 uint32_t next_maybe_unoccupied_index = 0;
3600
3601 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
3602 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
3603 TypeUnionField *union_field = &union_type->data.unionation.fields[field_i];
3604 AstNode *tag_value = field_node->data.struct_field.value;
3605
3606 if (tag_value == nullptr) {
3607 if (occupied_tag_values.size() == 0) {
3608 bigint_init_unsigned(&union_field->enum_field->value, next_maybe_unoccupied_index);
3609 next_maybe_unoccupied_index += 1;
3610 } else {
3611 BigInt proposed_value;
3612 for (;;) {
3613 bigint_init_unsigned(&proposed_value, next_maybe_unoccupied_index);
3614 next_maybe_unoccupied_index += 1;
3615 auto entry = occupied_tag_values.put_unique(proposed_value, field_node);
3616 if (entry != nullptr) {
3617 continue;
3618 }
3619 break;
3620 }
3621 bigint_init_bigint(&union_field->enum_field->value, &proposed_value);
3622 }
3623 }
3624 }
3625 }
3626 } else if (tag_type != nullptr) {
3627 for (uint32_t i = 0; i < tag_type->data.enumeration.src_field_count; i += 1) {
3628 TypeEnumField *enum_field = &tag_type->data.enumeration.fields[i];
3629 if (!covered_enum_fields[i]) {
3630 ErrorMsg *msg = add_node_error(g, decl_node,
3631 buf_sprintf("enum field missing: '%s'", buf_ptr(enum_field->name)));
3632 if (decl_node->type == NodeTypeContainerDecl) {
3633 AstNode *enum_decl_node = tag_type->data.enumeration.decl_node;
3634 AstNode *field_node = enum_decl_node->data.container_decl.fields.at(i);
3635 add_error_note(g, msg, field_node,
3636 buf_sprintf("declared here"));
3637 }
3638 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3639 }
3640 }
3641 heap::c_allocator.deallocate(covered_enum_fields, tag_type->data.enumeration.src_field_count);
3642 }
3643
3644 if (union_type->data.unionation.resolve_status == ResolveStatusInvalid) {
3645 return ErrorSemanticAnalyzeFail;
3646 }
3647
3648 union_type->data.unionation.resolve_loop_flag_zero_bits = false;
3649
3650 union_type->data.unionation.gen_field_count = gen_field_index;
3651 bool zero_bits = gen_field_index == 0 &&
3652 (tag_type == nullptr || !type_has_bits(g, tag_type));
3653 if (!zero_bits) {
3654 union_type->abi_size = SIZE_MAX;
3655 union_type->size_in_bits = SIZE_MAX;
3656 }
3657
3658 union_type->data.unionation.resolve_status = ResolveStatusZeroBitsKnown;
3659
3660 return ErrorNone;
3661}
3662
3663static Error resolve_opaque_type(CodeGen *g, ZigType *opaque_type) {
3664 Error err = ErrorNone;
3665 AstNode *container_node = opaque_type->data.opaque.decl_node;
3666 if (container_node != nullptr) {
3667 assert(container_node->type == NodeTypeContainerDecl);
3668 AstNodeContainerDecl *container_decl = &container_node->data.container_decl;
3669 for (size_t i = 0; i < container_decl->fields.length; i++) {
3670 AstNode *field_node = container_decl->fields.items[i];
3671 add_node_error(g, field_node, buf_create_from_str("opaque types cannot have fields"));
3672 err = ErrorSemanticAnalyzeFail;
3673 }
3674 }
3675 return err;
3676}
3677
3678void append_namespace_qualification(CodeGen *g, Buf *buf, ZigType *container_type) {
3679 if (g->root_import == container_type || buf_len(&container_type->name) == 0) return;
3680 buf_append_buf(buf, &container_type->name);
3681 buf_append_char(buf, NAMESPACE_SEP_CHAR);
3682}
3683
3684static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool is_test) {
3685 buf_resize(buf, 0);
3686
3687 Scope *scope = tld->parent_scope;
3688 while (scope->id != ScopeIdDecls) {
3689 scope = scope->parent;
3690 }
3691 ScopeDecls *decls_scope = reinterpret_cast<ScopeDecls *>(scope);
3692 append_namespace_qualification(g, buf, decls_scope->container_type);
3693 if (is_test) {
3694 buf_append_str(buf, "test \"");
3695 buf_append_buf(buf, tld->name);
3696 buf_append_char(buf, '"');
3697 } else {
3698 buf_append_buf(buf, tld->name);
3699 }
3700}
3701
3702static ZigFn *create_fn_raw(CodeGen *g, bool is_noinline) {
3703 ZigFn *fn_entry = heap::c_allocator.create<ZigFn>();
3704 fn_entry->stage1_zir = heap::c_allocator.create<Stage1Zir>();
3705 fn_entry->is_noinline = is_noinline;
3706
3707 return fn_entry;
3708}
3709
3710ZigFn *create_fn(CodeGen *g, AstNode *proto_node) {
3711 assert(proto_node->type == NodeTypeFnProto);
3712 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
3713
3714 ZigFn *fn_entry = create_fn_raw(g, fn_proto->fn_inline == FnInlineNever);
3715
3716 fn_entry->proto_node = proto_node;
3717 fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr :
3718 proto_node->data.fn_proto.fn_def_node->data.fn_def.body;
3719
3720 fn_entry->analyzed_executable.source_node = fn_entry->body_node;
3721
3722 return fn_entry;
3723}
3724
3725ZigType *get_test_fn_type(CodeGen *g) {
3726 if (g->test_fn_type)
3727 return g->test_fn_type;
3728
3729 FnTypeId fn_type_id = {0};
3730 fn_type_id.return_type = get_error_union_type(g, g->builtin_types.entry_global_error_set,
3731 g->builtin_types.entry_void);
3732 g->test_fn_type = get_fn_type(g, &fn_type_id);
3733 return g->test_fn_type;
3734}
3735
3736void add_var_export(CodeGen *g, ZigVar *var, const char *symbol_name, GlobalLinkageId linkage) {
3737 GlobalExport *global_export = var->export_list.add_one();
3738 memset(global_export, 0, sizeof(GlobalExport));
3739 buf_init_from_str(&global_export->name, symbol_name);
3740 global_export->linkage = linkage;
3741}
3742
3743void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage, CallingConvention cc) {
3744 CallingConvention winapi_cc = g->zig_target->arch == ZigLLVM_x86
3745 ? CallingConventionStdcall
3746 : CallingConventionC;
3747
3748 if (cc == CallingConventionC && strcmp(symbol_name, "main") == 0 && g->link_libc) {
3749 g->stage1.have_c_main = true;
3750 } else if (cc == winapi_cc && g->zig_target->os == OsWindows) {
3751 if (strcmp(symbol_name, "WinMain") == 0) {
3752 g->stage1.have_winmain = true;
3753 } else if (strcmp(symbol_name, "wWinMain") == 0) {
3754 g->stage1.have_wwinmain = true;
3755 } else if (strcmp(symbol_name, "WinMainCRTStartup") == 0) {
3756 g->stage1.have_winmain_crt_startup = true;
3757 } else if (strcmp(symbol_name, "wWinMainCRTStartup") == 0) {
3758 g->stage1.have_wwinmain_crt_startup = true;
3759 } else if (strcmp(symbol_name, "DllMainCRTStartup") == 0) {
3760 g->stage1.have_dllmain_crt_startup = true;
3761 }
3762 }
3763
3764 GlobalExport *fn_export = fn_table_entry->export_list.add_one();
3765 memset(fn_export, 0, sizeof(GlobalExport));
3766 buf_init_from_str(&fn_export->name, symbol_name);
3767 fn_export->linkage = linkage;
3768}
3769
3770static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
3771 AstNode *source_node = tld_fn->base.source_node;
3772 if (source_node->type == NodeTypeFnProto) {
3773 AstNodeFnProto *fn_proto = &source_node->data.fn_proto;
3774
3775 AstNode *fn_def_node = fn_proto->fn_def_node;
3776
3777 ZigFn *fn_table_entry = create_fn(g, source_node);
3778 tld_fn->fn_entry = fn_table_entry;
3779
3780 bool is_extern = (fn_table_entry->body_node == nullptr);
3781 if (fn_proto->is_export || is_extern) {
3782 buf_init_from_buf(&fn_table_entry->symbol_name, tld_fn->base.name);
3783 } else {
3784 get_fully_qualified_decl_name(g, &fn_table_entry->symbol_name, &tld_fn->base, false);
3785 }
3786
3787 if (!is_extern) {
3788 fn_table_entry->fndef_scope = create_fndef_scope(g,
3789 fn_table_entry->body_node, tld_fn->base.parent_scope, fn_table_entry);
3790
3791 for (size_t i = 0; i < fn_proto->params.length; i += 1) {
3792 AstNode *param_node = fn_proto->params.at(i);
3793 assert(param_node->type == NodeTypeParamDecl);
3794 if (param_node->data.param_decl.name == nullptr) {
3795 add_node_error(g, param_node, buf_sprintf("missing parameter name"));
3796 }
3797 }
3798 } else {
3799 fn_table_entry->inferred_async_node = inferred_async_none;
3800 g->external_symbol_names.put_unique(tld_fn->base.name, &tld_fn->base);
3801 }
3802
3803 Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope;
3804
3805 CallingConvention cc;
3806 if (fn_proto->callconv_expr != nullptr) {
3807 if (fn_proto->fn_inline == FnInlineAlways) {
3808 add_node_error(g, fn_proto->callconv_expr, buf_sprintf("explicit callconv incompatible with inline keyword"));
3809 }
3810 ZigType *cc_enum_value = get_builtin_type(g, "CallingConvention");
3811
3812 ZigValue *result_val = analyze_const_value(g, child_scope, fn_proto->callconv_expr,
3813 cc_enum_value, nullptr, UndefBad);
3814 if (type_is_invalid(result_val->type)) {
3815 fn_table_entry->type_entry = g->builtin_types.entry_invalid;
3816 tld_fn->base.resolution = TldResolutionInvalid;
3817 return;
3818 }
3819
3820 cc = (CallingConvention)bigint_as_u32(&result_val->data.x_enum_tag);
3821 } else {
3822 cc = cc_from_fn_proto(fn_proto);
3823 }
3824
3825 if (fn_proto->section_expr != nullptr) {
3826 if (!analyze_const_string(g, child_scope, fn_proto->section_expr, &fn_table_entry->section_name)) {
3827 fn_table_entry->type_entry = g->builtin_types.entry_invalid;
3828 tld_fn->base.resolution = TldResolutionInvalid;
3829 return;
3830 }
3831 }
3832
3833 fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry, cc);
3834
3835 if (type_is_invalid(fn_table_entry->type_entry)) {
3836 tld_fn->base.resolution = TldResolutionInvalid;
3837 return;
3838 }
3839
3840 const CallingConvention fn_cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc;
3841
3842 if (fn_proto->is_export) {
3843 switch (fn_cc) {
3844 case CallingConventionAsync:
3845 add_node_error(g, fn_def_node,
3846 buf_sprintf("exported function cannot be async"));
3847 fn_table_entry->type_entry = g->builtin_types.entry_invalid;
3848 tld_fn->base.resolution = TldResolutionInvalid;
3849 return;
3850 case CallingConventionInline:
3851 add_node_error(g, fn_def_node,
3852 buf_sprintf("exported function cannot be inline"));
3853 fn_table_entry->type_entry = g->builtin_types.entry_invalid;
3854 tld_fn->base.resolution = TldResolutionInvalid;
3855 return;
3856 case CallingConventionC:
3857 case CallingConventionNaked:
3858 case CallingConventionInterrupt:
3859 case CallingConventionSignal:
3860 case CallingConventionStdcall:
3861 case CallingConventionFastcall:
3862 case CallingConventionVectorcall:
3863 case CallingConventionThiscall:
3864 case CallingConventionAPCS:
3865 case CallingConventionAAPCS:
3866 case CallingConventionAAPCSVFP:
3867 case CallingConventionSysV:
3868 case CallingConventionWin64:
3869 case CallingConventionPtxKernel:
3870 case CallingConventionAmdgpuKernel:
3871 add_fn_export(g, fn_table_entry, buf_ptr(&fn_table_entry->symbol_name),
3872 GlobalLinkageIdStrong, fn_cc);
3873 break;
3874 case CallingConventionUnspecified:
3875 // An exported function without a specific calling
3876 // convention defaults to C
3877 add_fn_export(g, fn_table_entry, buf_ptr(&fn_table_entry->symbol_name),
3878 GlobalLinkageIdStrong, CallingConventionC);
3879 break;
3880 }
3881 }
3882
3883 if (!fn_table_entry->type_entry->data.fn.is_generic) {
3884 if (fn_def_node)
3885 g->fn_defs.append(fn_table_entry);
3886 }
3887
3888 // if the calling convention implies that it cannot be async, we save that for later
3889 // and leave the value to be nullptr to indicate that we have not emitted possible
3890 // compile errors for improperly calling async functions.
3891 if (fn_cc == CallingConventionAsync) {
3892 fn_table_entry->inferred_async_node = fn_table_entry->proto_node;
3893 }
3894 } else if (source_node->type == NodeTypeTestDecl) {
3895 ZigFn *fn_table_entry = create_fn_raw(g, false);
3896
3897 get_fully_qualified_decl_name(g, &fn_table_entry->symbol_name, &tld_fn->base, true);
3898
3899 tld_fn->fn_entry = fn_table_entry;
3900
3901 fn_table_entry->proto_node = source_node;
3902 fn_table_entry->fndef_scope = create_fndef_scope(g, source_node, tld_fn->base.parent_scope, fn_table_entry);
3903 fn_table_entry->type_entry = get_test_fn_type(g);
3904 fn_table_entry->body_node = source_node->data.test_decl.body;
3905
3906 g->fn_defs.append(fn_table_entry);
3907 g->test_fns.append(fn_table_entry);
3908
3909 } else {
3910 zig_unreachable();
3911 }
3912}
3913
3914static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) {
3915 assert(tld_comptime->base.source_node->type == NodeTypeCompTime);
3916 AstNode *expr_node = tld_comptime->base.source_node->data.comptime_expr.expr;
3917 analyze_const_value(g, tld_comptime->base.parent_scope, expr_node, g->builtin_types.entry_void,
3918 nullptr, UndefBad);
3919}
3920
3921static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
3922 bool is_export = false;
3923 if (tld->id == TldIdVar) {
3924 assert(tld->source_node->type == NodeTypeVariableDeclaration);
3925 is_export = tld->source_node->data.variable_declaration.is_export;
3926 } else if (tld->id == TldIdFn) {
3927 assert(tld->source_node->type == NodeTypeFnProto);
3928 is_export = tld->source_node->data.fn_proto.is_export;
3929
3930 if (!tld->source_node->data.fn_proto.is_extern &&
3931 tld->source_node->data.fn_proto.fn_def_node == nullptr)
3932 {
3933 add_node_error(g, tld->source_node, buf_sprintf("non-extern function has no body"));
3934 return;
3935 }
3936 if (!tld->source_node->data.fn_proto.is_extern &&
3937 tld->source_node->data.fn_proto.is_var_args)
3938 {
3939 add_node_error(g, tld->source_node, buf_sprintf("non-extern function is variadic"));
3940 return;
3941 }
3942 } else if (tld->id == TldIdUsingNamespace) {
3943 g->resolve_queue.append(tld);
3944 }
3945 if (is_export) {
3946 g->resolve_queue.append(tld);
3947
3948 auto entry = g->exported_symbol_names.put_unique(tld->name, tld);
3949 if (entry) {
3950 AstNode *other_source_node = entry->value->source_node;
3951 ErrorMsg *msg = add_node_error(g, tld->source_node,
3952 buf_sprintf("exported symbol collision: '%s'", buf_ptr(tld->name)));
3953 add_error_note(g, msg, other_source_node, buf_sprintf("other symbol here"));
3954 }
3955 }
3956
3957 if (tld->name != nullptr) {
3958 auto entry = decls_scope->decl_table.put_unique(tld->name, tld);
3959 if (entry) {
3960 Tld *other_tld = entry->value;
3961 if (other_tld->id == TldIdVar) {
3962 ZigVar *var = reinterpret_cast<TldVar *>(other_tld)->var;
3963 if (var != nullptr && var->var_type != nullptr && type_is_invalid(var->var_type)) {
3964 return; // already reported compile error
3965 }
3966 }
3967 ErrorMsg *msg = add_node_error(g, tld->source_node, buf_sprintf("redefinition of '%s'", buf_ptr(tld->name)));
3968 add_error_note(g, msg, other_tld->source_node, buf_sprintf("previous definition here"));
3969 return;
3970 }
3971 }
3972}
3973
3974static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) {
3975 assert(node->type == NodeTypeTestDecl);
3976
3977 if (!g->is_test_build)
3978 return;
3979
3980 ZigType *import = get_scope_import(&decls_scope->base);
3981 if (import->data.structure.root_struct->package != g->main_pkg)
3982 return;
3983
3984 Buf *decl_name_buf = node->data.test_decl.name;
3985 Buf *test_name;
3986
3987 if (decl_name_buf != nullptr) {
3988 test_name = g->test_name_prefix ?
3989 buf_sprintf("%s%s", buf_ptr(g->test_name_prefix), buf_ptr(decl_name_buf)) : decl_name_buf;
3990
3991 if (g->test_filter != nullptr && strstr(buf_ptr(test_name), buf_ptr(g->test_filter)) == nullptr) {
3992 return;
3993 }
3994 } else {
3995 // Unnamed test blocks are always executed.
3996 test_name = buf_sprintf("%s", g->test_name_prefix ? buf_ptr(g->test_name_prefix) : "");
3997 }
3998
3999 TldFn *tld_fn = heap::c_allocator.create<TldFn>();
4000 init_tld(&tld_fn->base, TldIdFn, test_name, VisibModPrivate, node, &decls_scope->base);
4001 g->resolve_queue.append(&tld_fn->base);
4002}
4003
4004static void preview_comptime_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) {
4005 assert(node->type == NodeTypeCompTime);
4006
4007 TldCompTime *tld_comptime = heap::c_allocator.create<TldCompTime>();
4008 init_tld(&tld_comptime->base, TldIdCompTime, nullptr, VisibModPrivate, node, &decls_scope->base);
4009 g->resolve_queue.append(&tld_comptime->base);
4010}
4011
4012void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node,
4013 Scope *parent_scope)
4014{
4015 tld->id = id;
4016 tld->name = name;
4017 tld->visib_mod = visib_mod;
4018 tld->source_node = source_node;
4019 tld->import = source_node ? source_node->owner : nullptr;
4020 tld->parent_scope = parent_scope;
4021}
4022
4023void update_compile_var(CodeGen *g, Buf *name, ZigValue *value) {
4024 ScopeDecls *builtin_scope = get_container_scope(g->compile_var_import);
4025 Tld *tld = find_container_decl(g, builtin_scope, name);
4026 assert(tld != nullptr);
4027 resolve_top_level_decl(g, tld, tld->source_node, false);
4028 assert(tld->id == TldIdVar && tld->resolution == TldResolutionOk);
4029 TldVar *tld_var = (TldVar *)tld;
4030 copy_const_val(g, tld_var->var->const_value, value);
4031 tld_var->var->var_type = value->type;
4032 tld_var->var->align_bytes = get_abi_alignment(g, value->type);
4033}
4034
4035void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
4036 switch (node->type) {
4037 case NodeTypeFnDef:
4038 scan_decls(g, decls_scope, node->data.fn_def.fn_proto);
4039 break;
4040 case NodeTypeVariableDeclaration:
4041 {
4042 Buf *name = node->data.variable_declaration.symbol;
4043 VisibMod visib_mod = node->data.variable_declaration.visib_mod;
4044 TldVar *tld_var = heap::c_allocator.create<TldVar>();
4045 init_tld(&tld_var->base, TldIdVar, name, visib_mod, node, &decls_scope->base);
4046 tld_var->extern_lib_name = node->data.variable_declaration.lib_name;
4047 add_top_level_decl(g, decls_scope, &tld_var->base);
4048 break;
4049 }
4050 case NodeTypeFnProto:
4051 {
4052 // if the name is missing, we immediately announce an error
4053 Buf *fn_name = node->data.fn_proto.name;
4054 if (fn_name == nullptr) {
4055 add_node_error(g, node, buf_sprintf("missing function name"));
4056 break;
4057 }
4058
4059 VisibMod visib_mod = node->data.fn_proto.visib_mod;
4060 TldFn *tld_fn = heap::c_allocator.create<TldFn>();
4061 init_tld(&tld_fn->base, TldIdFn, fn_name, visib_mod, node, &decls_scope->base);
4062 tld_fn->extern_lib_name = node->data.fn_proto.lib_name;
4063 add_top_level_decl(g, decls_scope, &tld_fn->base);
4064
4065 break;
4066 }
4067 case NodeTypeUsingNamespace: {
4068 VisibMod visib_mod = node->data.using_namespace.visib_mod;
4069 TldUsingNamespace *tld_using_namespace = heap::c_allocator.create<TldUsingNamespace>();
4070 init_tld(&tld_using_namespace->base, TldIdUsingNamespace, nullptr, visib_mod, node, &decls_scope->base);
4071 add_top_level_decl(g, decls_scope, &tld_using_namespace->base);
4072 decls_scope->use_decls.append(tld_using_namespace);
4073 break;
4074 }
4075 case NodeTypeTestDecl:
4076 preview_test_decl(g, node, decls_scope);
4077 break;
4078 case NodeTypeCompTime:
4079 preview_comptime_decl(g, node, decls_scope);
4080 break;
4081 case NodeTypeContainerDecl:
4082 case NodeTypeNoSuspend:
4083 case NodeTypeParamDecl:
4084 case NodeTypeReturnExpr:
4085 case NodeTypeDefer:
4086 case NodeTypeBlock:
4087 case NodeTypeGroupedExpr:
4088 case NodeTypeBinOpExpr:
4089 case NodeTypeCatchExpr:
4090 case NodeTypeFnCallExpr:
4091 case NodeTypeArrayAccessExpr:
4092 case NodeTypeSliceExpr:
4093 case NodeTypeFloatLiteral:
4094 case NodeTypeIntLiteral:
4095 case NodeTypeStringLiteral:
4096 case NodeTypeCharLiteral:
4097 case NodeTypeIdentifier:
4098 case NodeTypePrefixOpExpr:
4099 case NodeTypePointerType:
4100 case NodeTypeIfBoolExpr:
4101 case NodeTypeWhileExpr:
4102 case NodeTypeForExpr:
4103 case NodeTypeSwitchExpr:
4104 case NodeTypeSwitchProng:
4105 case NodeTypeSwitchRange:
4106 case NodeTypeBreak:
4107 case NodeTypeContinue:
4108 case NodeTypeUnreachable:
4109 case NodeTypeAsmExpr:
4110 case NodeTypeFieldAccessExpr:
4111 case NodeTypePtrDeref:
4112 case NodeTypeUnwrapOptional:
4113 case NodeTypeStructField:
4114 case NodeTypeContainerInitExpr:
4115 case NodeTypeStructValueField:
4116 case NodeTypeArrayType:
4117 case NodeTypeInferredArrayType:
4118 case NodeTypeErrorType:
4119 case NodeTypeIfErrorExpr:
4120 case NodeTypeIfOptional:
4121 case NodeTypeErrorSetDecl:
4122 case NodeTypeResume:
4123 case NodeTypeAwaitExpr:
4124 case NodeTypeSuspend:
4125 case NodeTypeEnumLiteral:
4126 case NodeTypeAnyFrameType:
4127 case NodeTypeErrorSetField:
4128 case NodeTypeAnyTypeField:
4129 zig_unreachable();
4130 }
4131}
4132
4133static Error resolve_decl_container(CodeGen *g, TldContainer *tld_container) {
4134 ZigType *type_entry = tld_container->type_entry;
4135 assert(type_entry);
4136
4137 switch (type_entry->id) {
4138 case ZigTypeIdStruct:
4139 return resolve_struct_type(g, tld_container->type_entry);
4140 case ZigTypeIdEnum:
4141 return resolve_enum_zero_bits(g, tld_container->type_entry);
4142 case ZigTypeIdUnion:
4143 return resolve_union_type(g, tld_container->type_entry);
4144 case ZigTypeIdOpaque:
4145 return resolve_opaque_type(g, tld_container->type_entry);
4146 default:
4147 zig_unreachable();
4148 }
4149}
4150
4151ZigType *validate_var_type(CodeGen *g, AstNodeVariableDeclaration *source_node, ZigType *type_entry) {
4152 switch (type_entry->id) {
4153 case ZigTypeIdInvalid:
4154 return g->builtin_types.entry_invalid;
4155 case ZigTypeIdOpaque:
4156 if (source_node->is_extern)
4157 return type_entry;
4158 ZIG_FALLTHROUGH;
4159 case ZigTypeIdUnreachable:
4160 case ZigTypeIdUndefined:
4161 case ZigTypeIdNull:
4162 add_node_error(g, source_node->type, buf_sprintf("variable of type '%s' not allowed",
4163 buf_ptr(&type_entry->name)));
4164 return g->builtin_types.entry_invalid;
4165 case ZigTypeIdComptimeFloat:
4166 case ZigTypeIdComptimeInt:
4167 case ZigTypeIdEnumLiteral:
4168 case ZigTypeIdMetaType:
4169 case ZigTypeIdVoid:
4170 case ZigTypeIdBool:
4171 case ZigTypeIdInt:
4172 case ZigTypeIdFloat:
4173 case ZigTypeIdPointer:
4174 case ZigTypeIdArray:
4175 case ZigTypeIdStruct:
4176 case ZigTypeIdOptional:
4177 case ZigTypeIdErrorUnion:
4178 case ZigTypeIdErrorSet:
4179 case ZigTypeIdEnum:
4180 case ZigTypeIdUnion:
4181 case ZigTypeIdFn:
4182 case ZigTypeIdBoundFn:
4183 case ZigTypeIdVector:
4184 case ZigTypeIdFnFrame:
4185 case ZigTypeIdAnyFrame:
4186 return type_entry;
4187 }
4188 zig_unreachable();
4189}
4190
4191// Set name to nullptr to make the variable anonymous (not visible to programmer).
4192// TODO merge with definition of add_local_var in ir.cpp
4193ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
4194 bool is_const, ZigValue *const_value, Tld *src_tld, ZigType *var_type)
4195{
4196 Error err;
4197 assert(const_value != nullptr);
4198 assert(var_type != nullptr);
4199
4200 ZigVar *variable_entry = heap::c_allocator.create<ZigVar>();
4201 variable_entry->const_value = const_value;
4202 variable_entry->var_type = var_type;
4203 variable_entry->parent_scope = parent_scope;
4204 variable_entry->shadowable = false;
4205 variable_entry->src_arg_index = SIZE_MAX;
4206
4207 assert(name);
4208 variable_entry->name = strdup(buf_ptr(name));
4209
4210 if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) {
4211 variable_entry->var_type = g->builtin_types.entry_invalid;
4212 } else {
4213 variable_entry->align_bytes = get_abi_alignment(g, var_type);
4214 }
4215
4216 Scope *child_scope;
4217 if (source_node && source_node->type == NodeTypeParamDecl) {
4218 child_scope = create_var_scope(g, source_node, parent_scope, variable_entry);
4219 } else {
4220 // it's already in the decls table
4221 child_scope = parent_scope;
4222 }
4223
4224
4225 variable_entry->src_is_const = is_const;
4226 variable_entry->gen_is_const = is_const;
4227 variable_entry->decl_node = source_node;
4228 variable_entry->child_scope = child_scope;
4229
4230
4231 return variable_entry;
4232}
4233
4234static void validate_export_var_type(CodeGen *g, ZigType* type, AstNode *source_node) {
4235 switch (type->id) {
4236 case ZigTypeIdMetaType:
4237 add_node_error(g, source_node, buf_sprintf("cannot export variable of type 'type'"));
4238 break;
4239 default:
4240 break;
4241 }
4242}
4243
4244static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) {
4245 AstNode *source_node = tld_var->base.source_node;
4246 AstNodeVariableDeclaration *var_decl = &source_node->data.variable_declaration;
4247
4248 bool is_const = var_decl->is_const;
4249 bool is_extern = var_decl->is_extern;
4250 bool is_export = var_decl->is_export;
4251 bool is_thread_local = var_decl->threadlocal_tok != 0;
4252
4253 ZigType *explicit_type = nullptr;
4254 if (var_decl->type) {
4255 if (tld_var->analyzing_type) {
4256 add_node_error(g, var_decl->type,
4257 buf_sprintf("type of '%s' depends on itself", buf_ptr(tld_var->base.name)));
4258 explicit_type = g->builtin_types.entry_invalid;
4259 } else {
4260 tld_var->analyzing_type = true;
4261 ZigType *proposed_type = analyze_type_expr(g, tld_var->base.parent_scope, var_decl->type);
4262 explicit_type = validate_var_type(g, var_decl, proposed_type);
4263 }
4264 }
4265
4266 assert(!is_export || !is_extern);
4267
4268 ZigValue *init_value = nullptr;
4269
4270 // TODO more validation for types that can't be used for export/extern variables
4271 ZigType *implicit_type = nullptr;
4272 if (explicit_type != nullptr && type_is_invalid(explicit_type)) {
4273 implicit_type = explicit_type;
4274 } else if (var_decl->expr) {
4275 init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type,
4276 var_decl->symbol, allow_lazy ? LazyOk : UndefOk);
4277 assert(init_value);
4278 implicit_type = init_value->type;
4279
4280 if (implicit_type->id == ZigTypeIdUnreachable) {
4281 add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
4282 implicit_type = g->builtin_types.entry_invalid;
4283 } else if ((!is_const || is_extern) &&
4284 (implicit_type->id == ZigTypeIdComptimeFloat ||
4285 implicit_type->id == ZigTypeIdComptimeInt ||
4286 implicit_type->id == ZigTypeIdEnumLiteral))
4287 {
4288 add_node_error(g, source_node, buf_sprintf("unable to infer variable type"));
4289 implicit_type = g->builtin_types.entry_invalid;
4290 } else if (implicit_type->id == ZigTypeIdNull) {
4291 add_node_error(g, source_node, buf_sprintf("unable to infer variable type"));
4292 implicit_type = g->builtin_types.entry_invalid;
4293 } else if (implicit_type->id == ZigTypeIdMetaType && !is_const) {
4294 add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));
4295 implicit_type = g->builtin_types.entry_invalid;
4296 }
4297 assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);
4298 } else if (!is_extern) {
4299 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
4300 implicit_type = g->builtin_types.entry_invalid;
4301 } else if (explicit_type == nullptr) {
4302 // extern variable without explicit type
4303 add_node_error(g, source_node, buf_sprintf("unable to infer variable type"));
4304 implicit_type = g->builtin_types.entry_invalid;
4305 }
4306
4307 ZigType *type = explicit_type ? explicit_type : implicit_type;
4308 assert(type != nullptr); // should have been caught by the parser
4309
4310 ZigValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(g, type);
4311
4312 tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,
4313 is_const, init_val, &tld_var->base, type);
4314 tld_var->var->is_thread_local = is_thread_local;
4315
4316 if (implicit_type != nullptr && type_is_invalid(implicit_type)) {
4317 tld_var->var->var_type = g->builtin_types.entry_invalid;
4318 }
4319
4320 if (var_decl->align_expr != nullptr) {
4321 if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) {
4322 tld_var->var->var_type = g->builtin_types.entry_invalid;
4323 }
4324 }
4325
4326 if (var_decl->section_expr != nullptr) {
4327 if (!analyze_const_string(g, tld_var->base.parent_scope, var_decl->section_expr, &tld_var->var->section_name)) {
4328 tld_var->var->section_name = nullptr;
4329 }
4330 }
4331
4332 if (is_thread_local && is_const) {
4333 add_node_error(g, source_node, buf_sprintf("threadlocal variable cannot be constant"));
4334 }
4335
4336 if (is_export) {
4337 validate_export_var_type(g, type, source_node);
4338 add_var_export(g, tld_var->var, tld_var->var->name, GlobalLinkageIdStrong);
4339 }
4340
4341 if (is_extern) {
4342 g->external_symbol_names.put_unique(tld_var->base.name, &tld_var->base);
4343 }
4344
4345 g->global_vars.append(tld_var);
4346}
4347
4348static void add_symbols_from_container(CodeGen *g, TldUsingNamespace *src_using_namespace,
4349 TldUsingNamespace *dst_using_namespace, ScopeDecls* dest_decls_scope)
4350{
4351 if (src_using_namespace->base.resolution == TldResolutionUnresolved ||
4352 src_using_namespace->base.resolution == TldResolutionResolving)
4353 {
4354 assert(src_using_namespace->base.parent_scope->id == ScopeIdDecls);
4355 ScopeDecls *src_decls_scope = (ScopeDecls *)src_using_namespace->base.parent_scope;
4356 preview_use_decl(g, src_using_namespace, src_decls_scope);
4357 if (src_using_namespace != dst_using_namespace) {
4358 resolve_use_decl(g, src_using_namespace, src_decls_scope);
4359 }
4360 }
4361
4362 ZigValue *use_expr = src_using_namespace->using_namespace_value;
4363 if (type_is_invalid(use_expr->type)) {
4364 dest_decls_scope->any_imports_failed = true;
4365 return;
4366 }
4367
4368 dst_using_namespace->base.resolution = TldResolutionOk;
4369
4370 assert(use_expr->special != ConstValSpecialRuntime);
4371
4372 // The source scope for the imported symbols
4373 ScopeDecls *src_scope = get_container_scope(use_expr->data.x_type);
4374 // The top-level container where the symbols are defined, it's used in the
4375 // loop below in order to exclude the ones coming from an import statement
4376 ZigType *src_import = get_scope_import(&src_scope->base);
4377 assert(src_import != nullptr);
4378
4379 if (src_scope->any_imports_failed) {
4380 dest_decls_scope->any_imports_failed = true;
4381 }
4382
4383 auto it = src_scope->decl_table.entry_iterator();
4384 for (;;) {
4385 auto *entry = it.next();
4386 if (!entry)
4387 break;
4388
4389 Buf *target_tld_name = entry->key;
4390 Tld *target_tld = entry->value;
4391
4392 if (target_tld->visib_mod == VisibModPrivate) {
4393 continue;
4394 }
4395
4396 if (target_tld->import != src_import) {
4397 continue;
4398 }
4399
4400 auto existing_entry = dest_decls_scope->decl_table.put_unique(target_tld_name, target_tld);
4401 if (existing_entry) {
4402 Tld *existing_decl = existing_entry->value;
4403 if (existing_decl != target_tld) {
4404 ErrorMsg *msg = add_node_error(g, dst_using_namespace->base.source_node,
4405 buf_sprintf("import of '%s' overrides existing definition",
4406 buf_ptr(target_tld_name)));
4407 add_error_note(g, msg, existing_decl->source_node, buf_sprintf("previous definition here"));
4408 add_error_note(g, msg, target_tld->source_node, buf_sprintf("imported definition here"));
4409 }
4410 }
4411 }
4412
4413 for (size_t i = 0; i < src_scope->use_decls.length; i += 1) {
4414 TldUsingNamespace *tld_using_namespace = src_scope->use_decls.at(i);
4415 if (tld_using_namespace->base.visib_mod != VisibModPrivate)
4416 add_symbols_from_container(g, tld_using_namespace, dst_using_namespace, dest_decls_scope);
4417 }
4418}
4419
4420static void resolve_use_decl(CodeGen *g, TldUsingNamespace *tld_using_namespace, ScopeDecls *dest_decls_scope) {
4421 if (tld_using_namespace->base.resolution == TldResolutionOk ||
4422 tld_using_namespace->base.resolution == TldResolutionInvalid)
4423 {
4424 return;
4425 }
4426 add_symbols_from_container(g, tld_using_namespace, tld_using_namespace, dest_decls_scope);
4427}
4428
4429static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, ScopeDecls *dest_decls_scope) {
4430 if (using_namespace->base.resolution == TldResolutionOk ||
4431 using_namespace->base.resolution == TldResolutionInvalid ||
4432 using_namespace->using_namespace_value != nullptr)
4433 {
4434 return;
4435 }
4436
4437 using_namespace->base.resolution = TldResolutionResolving;
4438 assert(using_namespace->base.source_node->type == NodeTypeUsingNamespace);
4439 ZigValue *result = analyze_const_value(g, &dest_decls_scope->base,
4440 using_namespace->base.source_node->data.using_namespace.expr, g->builtin_types.entry_type,
4441 nullptr, UndefBad);
4442 using_namespace->using_namespace_value = result;
4443
4444 if (type_is_invalid(result->type)) {
4445 dest_decls_scope->any_imports_failed = true;
4446 using_namespace->base.resolution = TldResolutionInvalid;
4447 using_namespace->using_namespace_value = g->invalid_inst_gen->value;
4448 return;
4449 }
4450
4451 if (!is_container(result->data.x_type)) {
4452 add_node_error(g, using_namespace->base.source_node,
4453 buf_sprintf("expected struct, enum, or union; found '%s'", buf_ptr(&result->data.x_type->name)));
4454 dest_decls_scope->any_imports_failed = true;
4455 using_namespace->base.resolution = TldResolutionInvalid;
4456 using_namespace->using_namespace_value = g->invalid_inst_gen->value;
4457 return;
4458 }
4459}
4460
4461void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy) {
4462 bool want_resolve_lazy = tld->resolution == TldResolutionOkLazy && !allow_lazy;
4463 if (tld->resolution != TldResolutionUnresolved && !want_resolve_lazy)
4464 return;
4465
4466 tld->resolution = TldResolutionResolving;
4467 update_progress_display(g);
4468
4469 switch (tld->id) {
4470 case TldIdVar: {
4471 TldVar *tld_var = (TldVar *)tld;
4472 if (want_resolve_lazy) {
4473 ir_resolve_lazy(g, source_node, tld_var->var->const_value);
4474 } else {
4475 resolve_decl_var(g, tld_var, allow_lazy);
4476 }
4477 tld->resolution = allow_lazy ? TldResolutionOkLazy : TldResolutionOk;
4478 break;
4479 }
4480 case TldIdFn: {
4481 TldFn *tld_fn = (TldFn *)tld;
4482 resolve_decl_fn(g, tld_fn);
4483
4484 tld->resolution = TldResolutionOk;
4485 break;
4486 }
4487 case TldIdContainer: {
4488 TldContainer *tld_container = (TldContainer *)tld;
4489 resolve_decl_container(g, tld_container);
4490
4491 tld->resolution = TldResolutionOk;
4492 break;
4493 }
4494 case TldIdCompTime: {
4495 TldCompTime *tld_comptime = (TldCompTime *)tld;
4496 resolve_decl_comptime(g, tld_comptime);
4497
4498 tld->resolution = TldResolutionOk;
4499 break;
4500 }
4501 case TldIdUsingNamespace: {
4502 TldUsingNamespace *tld_using_namespace = (TldUsingNamespace *)tld;
4503 assert(tld_using_namespace->base.parent_scope->id == ScopeIdDecls);
4504 ScopeDecls *dest_decls_scope = (ScopeDecls *)tld_using_namespace->base.parent_scope;
4505 preview_use_decl(g, tld_using_namespace, dest_decls_scope);
4506 resolve_use_decl(g, tld_using_namespace, dest_decls_scope);
4507
4508 tld->resolution = TldResolutionOk;
4509 break;
4510 }
4511 }
4512}
4513
4514void resolve_container_usingnamespace_decls(CodeGen *g, ScopeDecls *decls_scope) {
4515 // resolve all the using_namespace decls
4516 for (size_t i = 0; i < decls_scope->use_decls.length; i += 1) {
4517 TldUsingNamespace *tld_using_namespace = decls_scope->use_decls.at(i);
4518 if (tld_using_namespace->base.resolution == TldResolutionUnresolved) {
4519 preview_use_decl(g, tld_using_namespace, decls_scope);
4520 resolve_use_decl(g, tld_using_namespace, decls_scope);
4521 }
4522 }
4523
4524}
4525
4526Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name) {
4527 resolve_container_usingnamespace_decls(g, decls_scope);
4528 auto entry = decls_scope->decl_table.maybe_get(name);
4529 return (entry == nullptr) ? nullptr : entry->value;
4530}
4531
4532Tld *find_decl(CodeGen *g, Scope *scope, Buf *name) {
4533 while (scope) {
4534 if (scope->id == ScopeIdDecls) {
4535 ScopeDecls *decls_scope = (ScopeDecls *)scope;
4536
4537 Tld *result = find_container_decl(g, decls_scope, name);
4538 if (result != nullptr)
4539 return result;
4540 }
4541 scope = scope->parent;
4542 }
4543 return nullptr;
4544}
4545
4546ZigVar *find_variable(CodeGen *g, Scope *scope, Buf *name, ScopeFnDef **crossed_fndef_scope) {
4547 ScopeFnDef *my_crossed_fndef_scope = nullptr;
4548 while (scope) {
4549 if (scope->id == ScopeIdVarDecl) {
4550 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
4551 if (buf_eql_str(name, var_scope->var->name)) {
4552 if (crossed_fndef_scope != nullptr)
4553 *crossed_fndef_scope = my_crossed_fndef_scope;
4554 return var_scope->var;
4555 }
4556 } else if (scope->id == ScopeIdDecls) {
4557 ScopeDecls *decls_scope = (ScopeDecls *)scope;
4558 auto entry = decls_scope->decl_table.maybe_get(name);
4559 if (entry) {
4560 Tld *tld = entry->value;
4561 if (tld->id == TldIdVar) {
4562 TldVar *tld_var = (TldVar *)tld;
4563 if (tld_var->var) {
4564 if (crossed_fndef_scope != nullptr)
4565 *crossed_fndef_scope = nullptr;
4566 return tld_var->var;
4567 }
4568 }
4569 }
4570 } else if (scope->id == ScopeIdFnDef) {
4571 my_crossed_fndef_scope = (ScopeFnDef *)scope;
4572 }
4573 scope = scope->parent;
4574 }
4575
4576 return nullptr;
4577}
4578
4579ZigFn *scope_fn_entry(Scope *scope) {
4580 while (scope) {
4581 if (scope->id == ScopeIdFnDef) {
4582 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
4583 return fn_scope->fn_entry;
4584 }
4585 scope = scope->parent;
4586 }
4587 return nullptr;
4588}
4589
4590ZigPackage *scope_package(Scope *scope) {
4591 ZigType *import = get_scope_import(scope);
4592 assert(is_top_level_struct(import));
4593 return import->data.structure.root_struct->package;
4594}
4595
4596TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name) {
4597 assert(enum_type->id == ZigTypeIdEnum);
4598 if (enum_type->data.enumeration.src_field_count == 0)
4599 return nullptr;
4600 auto entry = enum_type->data.enumeration.fields_by_name.maybe_get(name);
4601 if (entry == nullptr)
4602 return nullptr;
4603 return entry->value;
4604}
4605
4606TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name) {
4607 assert(type_entry->id == ZigTypeIdStruct);
4608 if (type_entry->data.structure.resolve_status == ResolveStatusBeingInferred) {
4609 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
4610 TypeStructField *field = type_entry->data.structure.fields[i];
4611 if (buf_eql_buf(field->name, name))
4612 return field;
4613 }
4614 return nullptr;
4615 } else {
4616 assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
4617 if (type_entry->data.structure.src_field_count == 0)
4618 return nullptr;
4619 auto entry = type_entry->data.structure.fields_by_name.maybe_get(name);
4620 if (entry == nullptr)
4621 return nullptr;
4622 return entry->value;
4623 }
4624}
4625
4626TypeUnionField *find_union_type_field(ZigType *type_entry, Buf *name) {
4627 assert(type_entry->id == ZigTypeIdUnion);
4628 assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
4629 if (type_entry->data.unionation.src_field_count == 0)
4630 return nullptr;
4631 auto entry = type_entry->data.unionation.fields_by_name.maybe_get(name);
4632 if (entry == nullptr)
4633 return nullptr;
4634 return entry->value;
4635}
4636
4637TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag) {
4638 assert(type_entry->id == ZigTypeIdUnion);
4639 assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
4640 for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) {
4641 TypeUnionField *field = &type_entry->data.unionation.fields[i];
4642 if (bigint_cmp(&field->enum_field->value, tag) == CmpEQ) {
4643 return field;
4644 }
4645 }
4646 return nullptr;
4647}
4648
4649TypeEnumField *find_enum_field_by_tag(ZigType *enum_type, const BigInt *tag) {
4650 assert(type_is_resolved(enum_type, ResolveStatusZeroBitsKnown));
4651 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {
4652 TypeEnumField *field = &enum_type->data.enumeration.fields[i];
4653 if (bigint_cmp(&field->value, tag) == CmpEQ) {
4654 return field;
4655 }
4656 }
4657 return nullptr;
4658}
4659
4660
4661bool is_container(ZigType *type_entry) {
4662 switch (type_entry->id) {
4663 case ZigTypeIdInvalid:
4664 zig_unreachable();
4665 case ZigTypeIdStruct:
4666 return type_entry->data.structure.special != StructSpecialSlice;
4667 case ZigTypeIdEnum:
4668 case ZigTypeIdUnion:
4669 case ZigTypeIdOpaque:
4670 return true;
4671 case ZigTypeIdPointer:
4672 case ZigTypeIdMetaType:
4673 case ZigTypeIdVoid:
4674 case ZigTypeIdBool:
4675 case ZigTypeIdUnreachable:
4676 case ZigTypeIdInt:
4677 case ZigTypeIdFloat:
4678 case ZigTypeIdArray:
4679 case ZigTypeIdComptimeFloat:
4680 case ZigTypeIdComptimeInt:
4681 case ZigTypeIdEnumLiteral:
4682 case ZigTypeIdUndefined:
4683 case ZigTypeIdNull:
4684 case ZigTypeIdOptional:
4685 case ZigTypeIdErrorUnion:
4686 case ZigTypeIdErrorSet:
4687 case ZigTypeIdFn:
4688 case ZigTypeIdBoundFn:
4689 case ZigTypeIdVector:
4690 case ZigTypeIdFnFrame:
4691 case ZigTypeIdAnyFrame:
4692 return false;
4693 }
4694 zig_unreachable();
4695}
4696
4697bool is_ref(ZigType *type_entry) {
4698 return type_entry->id == ZigTypeIdPointer && type_entry->data.pointer.ptr_len == PtrLenSingle;
4699}
4700
4701bool is_array_ref(ZigType *type_entry) {
4702 ZigType *array = is_ref(type_entry) ?
4703 type_entry->data.pointer.child_type : type_entry;
4704 return array->id == ZigTypeIdArray;
4705}
4706
4707bool is_container_ref(ZigType *parent_ty) {
4708 ZigType *ty = is_ref(parent_ty) ? parent_ty->data.pointer.child_type : parent_ty;
4709 return is_slice(ty) || is_container(ty);
4710}
4711
4712ZigType *container_ref_type(ZigType *type_entry) {
4713 assert(is_container_ref(type_entry));
4714 return is_ref(type_entry) ?
4715 type_entry->data.pointer.child_type : type_entry;
4716}
4717
4718ZigType *get_src_ptr_type(ZigType *type) {
4719 if (type->id == ZigTypeIdPointer) return type;
4720 if (type->id == ZigTypeIdFn) return type;
4721 if (type->id == ZigTypeIdAnyFrame) return type;
4722 if (type->id == ZigTypeIdOptional) {
4723 if (type->data.maybe.child_type->id == ZigTypeIdPointer) {
4724 return type->data.maybe.child_type->data.pointer.allow_zero ? nullptr : type->data.maybe.child_type;
4725 }
4726 if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;
4727 if (type->data.maybe.child_type->id == ZigTypeIdAnyFrame) return type->data.maybe.child_type;
4728 }
4729 return nullptr;
4730}
4731
4732Error get_codegen_ptr_type(CodeGen *g, ZigType *type, ZigType **result) {
4733 Error err;
4734
4735 ZigType *ty = get_src_ptr_type(type);
4736 if (ty == nullptr) {
4737 *result = nullptr;
4738 return ErrorNone;
4739 }
4740
4741 bool has_bits;
4742 if ((err = type_has_bits2(g, ty, &has_bits))) return err;
4743 if (!has_bits) {
4744 *result = nullptr;
4745 return ErrorNone;
4746 }
4747
4748 *result = ty;
4749 return ErrorNone;
4750}
4751
4752ZigType *get_codegen_ptr_type_bail(CodeGen *g, ZigType *type) {
4753 Error err;
4754 ZigType *result;
4755 if ((err = get_codegen_ptr_type(g, type, &result))) {
4756 codegen_report_errors_and_exit(g);
4757 }
4758 return result;
4759}
4760
4761bool type_is_nonnull_ptr(CodeGen *g, ZigType *type) {
4762 Error err;
4763 bool result;
4764 if ((err = type_is_nonnull_ptr2(g, type, &result))) {
4765 codegen_report_errors_and_exit(g);
4766 }
4767 return result;
4768}
4769
4770Error type_is_nonnull_ptr2(CodeGen *g, ZigType *type, bool *result) {
4771 Error err;
4772 ZigType *ptr_type;
4773 if ((err = get_codegen_ptr_type(g, type, &ptr_type))) return err;
4774 *result = ptr_type == type && !ptr_allows_addr_zero(type);
4775 return ErrorNone;
4776}
4777
4778uint32_t get_async_frame_align_bytes(CodeGen *g) {
4779 // Due to how the frame structure is built the minimum alignment is the one
4780 // of a usize (or pointer).
4781 // label (grep this): [fn_frame_struct_layout]
4782 return max(g->builtin_types.entry_usize->abi_align, target_fn_align(g->zig_target));
4783}
4784
4785uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
4786 ZigType *ptr_type;
4787 if (type->id == ZigTypeIdStruct) {
4788 assert(type->data.structure.special == StructSpecialSlice);
4789 TypeStructField *ptr_field = type->data.structure.fields[slice_ptr_index];
4790 ptr_type = resolve_struct_field_type(g, ptr_field);
4791 } else {
4792 ptr_type = get_src_ptr_type(type);
4793 }
4794 if (ptr_type->id == ZigTypeIdPointer) {
4795 return (ptr_type->data.pointer.explicit_alignment == 0) ?
4796 get_abi_alignment(g, ptr_type->data.pointer.child_type) : ptr_type->data.pointer.explicit_alignment;
4797 } else if (ptr_type->id == ZigTypeIdFn) {
4798 return (ptr_type->data.fn.fn_type_id.alignment == 0) ?
4799 target_fn_ptr_align(g->zig_target) : ptr_type->data.fn.fn_type_id.alignment;
4800 } else if (ptr_type->id == ZigTypeIdAnyFrame) {
4801 return get_async_frame_align_bytes(g);
4802 } else {
4803 zig_unreachable();
4804 }
4805}
4806
4807bool get_ptr_const(CodeGen *g, ZigType *type) {
4808 ZigType *ptr_type;
4809 if (type->id == ZigTypeIdStruct) {
4810 assert(type->data.structure.special == StructSpecialSlice);
4811 TypeStructField *ptr_field = type->data.structure.fields[slice_ptr_index];
4812 ptr_type = resolve_struct_field_type(g, ptr_field);
4813 } else {
4814 ptr_type = get_src_ptr_type(type);
4815 }
4816 if (ptr_type->id == ZigTypeIdPointer) {
4817 return ptr_type->data.pointer.is_const;
4818 } else if (ptr_type->id == ZigTypeIdFn) {
4819 return true;
4820 } else if (ptr_type->id == ZigTypeIdAnyFrame) {
4821 return true;
4822 } else {
4823 zig_unreachable();
4824 }
4825}
4826
4827AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index) {
4828 if (fn_entry->param_source_nodes)
4829 return fn_entry->param_source_nodes[index];
4830 else if (fn_entry->proto_node)
4831 return fn_entry->proto_node->data.fn_proto.params.at(index);
4832 else
4833 return nullptr;
4834}
4835
4836static Error define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
4837 Error err;
4838 ZigType *fn_type = fn_table_entry->type_entry;
4839 assert(!fn_type->data.fn.is_generic);
4840 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
4841 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
4842 FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
4843 AstNode *param_decl_node = get_param_decl_node(fn_table_entry, i);
4844 Buf *param_name;
4845 bool is_var_args = param_decl_node && param_decl_node->data.param_decl.is_var_args;
4846 if (param_decl_node && !is_var_args) {
4847 param_name = param_decl_node->data.param_decl.name;
4848 } else {
4849 param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i);
4850 }
4851 if (param_name == nullptr) {
4852 continue;
4853 }
4854
4855 ZigType *param_type = param_info->type;
4856 if ((err = type_resolve(g, param_type, ResolveStatusSizeKnown))) {
4857 return err;
4858 }
4859
4860 bool is_noalias = param_info->is_noalias;
4861 if (is_noalias) {
4862 ZigType *ptr_type;
4863 if ((err = get_codegen_ptr_type(g, param_type, &ptr_type))) return err;
4864 if (ptr_type == nullptr) {
4865 add_node_error(g, param_decl_node, buf_sprintf("noalias on non-pointer parameter"));
4866 }
4867 }
4868
4869 ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,
4870 param_name, true, create_const_runtime(g, param_type), nullptr, param_type);
4871 var->src_arg_index = i;
4872 fn_table_entry->child_scope = var->child_scope;
4873 var->shadowable = var->shadowable || is_var_args;
4874
4875 if (type_has_bits(g, param_type)) {
4876 fn_table_entry->variable_list.append(var);
4877 }
4878 }
4879
4880 return ErrorNone;
4881}
4882
4883bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node) {
4884 assert(err_set_type->id == ZigTypeIdErrorSet);
4885 ZigFn *infer_fn = err_set_type->data.error_set.infer_fn;
4886 if (infer_fn != nullptr && err_set_type->data.error_set.incomplete) {
4887 if (infer_fn->anal_state == FnAnalStateInvalid) {
4888 return false;
4889 } else if (infer_fn->anal_state == FnAnalStateReady) {
4890 analyze_fn_body(g, infer_fn);
4891 if (infer_fn->anal_state == FnAnalStateInvalid ||
4892 err_set_type->data.error_set.incomplete)
4893 {
4894 assert(g->errors.length != 0);
4895 return false;
4896 }
4897 } else {
4898 add_node_error(g, source_node,
4899 buf_sprintf("cannot resolve inferred error set '%s': function '%s' not fully analyzed yet",
4900 buf_ptr(&err_set_type->name), buf_ptr(&err_set_type->data.error_set.infer_fn->symbol_name)));
4901 return false;
4902 }
4903 }
4904 return true;
4905}
4906
4907static void resolve_async_fn_frame(CodeGen *g, ZigFn *fn) {
4908 ZigType *frame_type = get_fn_frame_type(g, fn);
4909 Error err;
4910 if ((err = type_resolve(g, frame_type, ResolveStatusSizeKnown))) {
4911 if (g->trace_err != nullptr && frame_type->data.frame.resolve_loop_src_node != nullptr &&
4912 !frame_type->data.frame.reported_loop_err)
4913 {
4914 frame_type->data.frame.reported_loop_err = true;
4915 g->trace_err = add_error_note(g, g->trace_err, frame_type->data.frame.resolve_loop_src_node,
4916 buf_sprintf("when analyzing type '%s' here", buf_ptr(&frame_type->name)));
4917 }
4918 fn->anal_state = FnAnalStateInvalid;
4919 return;
4920 }
4921}
4922
4923bool fn_is_async(ZigFn *fn) {
4924 assert(fn->inferred_async_node != nullptr);
4925 assert(fn->inferred_async_node != inferred_async_checking);
4926 return fn->inferred_async_node != inferred_async_none;
4927}
4928
4929void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {
4930 assert(fn->inferred_async_node != nullptr);
4931 assert(fn->inferred_async_node != inferred_async_checking);
4932 assert(fn->inferred_async_node != inferred_async_none);
4933 if (fn->inferred_async_fn != nullptr) {
4934 ErrorMsg *new_msg;
4935 if (fn->inferred_async_node->type == NodeTypeAwaitExpr) {
4936 new_msg = add_error_note(g, msg, fn->inferred_async_node,
4937 buf_create_from_str("await here is a suspend point"));
4938 } else {
4939 new_msg = add_error_note(g, msg, fn->inferred_async_node,
4940 buf_sprintf("async function call here"));
4941 }
4942 return add_async_error_notes(g, new_msg, fn->inferred_async_fn);
4943 } else if (fn->inferred_async_node->type == NodeTypeFnProto) {
4944 add_error_note(g, msg, fn->inferred_async_node,
4945 buf_sprintf("async calling convention here"));
4946 } else if (fn->inferred_async_node->type == NodeTypeSuspend) {
4947 add_error_note(g, msg, fn->inferred_async_node,
4948 buf_sprintf("suspends here"));
4949 } else if (fn->inferred_async_node->type == NodeTypeAwaitExpr) {
4950 add_error_note(g, msg, fn->inferred_async_node,
4951 buf_sprintf("await here is a suspend point"));
4952 } else if (fn->inferred_async_node->type == NodeTypeFnCallExpr &&
4953 fn->inferred_async_node->data.fn_call_expr.modifier == CallModifierBuiltin)
4954 {
4955 add_error_note(g, msg, fn->inferred_async_node,
4956 buf_sprintf("@frame() causes function to be async"));
4957 } else {
4958 add_error_note(g, msg, fn->inferred_async_node,
4959 buf_sprintf("suspends here"));
4960 }
4961}
4962
4963// ErrorNone - not async
4964// ErrorIsAsync - yes async
4965// ErrorSemanticAnalyzeFail - compile error emitted result is invalid
4966static Error analyze_callee_async(CodeGen *g, ZigFn *fn, ZigFn *callee, AstNode *call_node,
4967 bool must_not_be_async, CallModifier modifier)
4968{
4969 if (modifier == CallModifierNoSuspend)
4970 return ErrorNone;
4971 bool callee_is_async = false;
4972 switch (callee->type_entry->data.fn.fn_type_id.cc) {
4973 case CallingConventionUnspecified:
4974 break;
4975 case CallingConventionAsync:
4976 callee_is_async = true;
4977 break;
4978 default:
4979 return ErrorNone;
4980 }
4981 if (!callee_is_async) {
4982 if (callee->anal_state == FnAnalStateReady) {
4983 analyze_fn_body(g, callee);
4984 if (callee->anal_state == FnAnalStateInvalid) {
4985 return ErrorSemanticAnalyzeFail;
4986 }
4987 }
4988 if (callee->anal_state == FnAnalStateComplete) {
4989 analyze_fn_async(g, callee, true);
4990 if (callee->anal_state == FnAnalStateInvalid) {
4991 if (g->trace_err != nullptr) {
4992 g->trace_err = add_error_note(g, g->trace_err, call_node,
4993 buf_sprintf("while checking if '%s' is async", buf_ptr(&fn->symbol_name)));
4994 }
4995 return ErrorSemanticAnalyzeFail;
4996 }
4997 callee_is_async = fn_is_async(callee);
4998 } else {
4999 // If it's already been determined, use that value. Otherwise
5000 // assume non-async, emit an error later if it turned out to be async.
5001 if (callee->inferred_async_node == nullptr ||
5002 callee->inferred_async_node == inferred_async_checking)
5003 {
5004 callee->assumed_non_async = call_node;
5005 callee_is_async = false;
5006 } else {
5007 callee_is_async = callee->inferred_async_node != inferred_async_none;
5008 }
5009 }
5010 }
5011 if (callee_is_async) {
5012 bool bad_recursion = (fn->inferred_async_node == inferred_async_none);
5013 fn->inferred_async_node = call_node;
5014 fn->inferred_async_fn = callee;
5015 if (must_not_be_async) {
5016 ErrorMsg *msg = add_node_error(g, fn->proto_node,
5017 buf_sprintf("function with calling convention '%s' cannot be async",
5018 calling_convention_name(fn->type_entry->data.fn.fn_type_id.cc)));
5019 add_async_error_notes(g, msg, fn);
5020 return ErrorSemanticAnalyzeFail;
5021 }
5022 if (bad_recursion) {
5023 ErrorMsg *msg = add_node_error(g, fn->proto_node,
5024 buf_sprintf("recursive function cannot be async"));
5025 add_async_error_notes(g, msg, fn);
5026 return ErrorSemanticAnalyzeFail;
5027 }
5028 if (fn->assumed_non_async != nullptr) {
5029 ErrorMsg *msg = add_node_error(g, fn->proto_node,
5030 buf_sprintf("unable to infer whether '%s' should be async",
5031 buf_ptr(&fn->symbol_name)));
5032 add_error_note(g, msg, fn->assumed_non_async,
5033 buf_sprintf("assumed to be non-async here"));
5034 add_async_error_notes(g, msg, fn);
5035 fn->anal_state = FnAnalStateInvalid;
5036 return ErrorSemanticAnalyzeFail;
5037 }
5038 return ErrorIsAsync;
5039 }
5040 return ErrorNone;
5041}
5042
5043// This function resolves functions being inferred async.
5044static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
5045 if (fn->inferred_async_node == inferred_async_checking) {
5046 // TODO call graph cycle detected, disallow the recursion
5047 fn->inferred_async_node = inferred_async_none;
5048 return;
5049 }
5050 if (fn->inferred_async_node == inferred_async_none) {
5051 return;
5052 }
5053 if (fn->inferred_async_node != nullptr) {
5054 if (resolve_frame) {
5055 resolve_async_fn_frame(g, fn);
5056 }
5057 return;
5058 }
5059 fn->inferred_async_node = inferred_async_checking;
5060
5061 bool must_not_be_async = false;
5062 if (fn->type_entry->data.fn.fn_type_id.cc != CallingConventionUnspecified) {
5063 must_not_be_async = true;
5064 fn->inferred_async_node = inferred_async_none;
5065 }
5066
5067 for (size_t i = 0; i < fn->call_list.length; i += 1) {
5068 Stage1AirInstCall *call = fn->call_list.at(i);
5069 if (call->fn_entry == nullptr) {
5070 // TODO function pointer call here, could be anything
5071 continue;
5072 }
5073 switch (analyze_callee_async(g, fn, call->fn_entry, call->base.source_node, must_not_be_async,
5074 call->modifier))
5075 {
5076 case ErrorSemanticAnalyzeFail:
5077 fn->anal_state = FnAnalStateInvalid;
5078 return;
5079 case ErrorNone:
5080 continue;
5081 case ErrorIsAsync:
5082 if (resolve_frame) {
5083 resolve_async_fn_frame(g, fn);
5084 }
5085 return;
5086 default:
5087 zig_unreachable();
5088 }
5089 }
5090 for (size_t i = 0; i < fn->await_list.length; i += 1) {
5091 Stage1AirInstAwait *await = fn->await_list.at(i);
5092 if (await->is_nosuspend) continue;
5093 switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async,
5094 CallModifierNone))
5095 {
5096 case ErrorSemanticAnalyzeFail:
5097 fn->anal_state = FnAnalStateInvalid;
5098 return;
5099 case ErrorNone:
5100 continue;
5101 case ErrorIsAsync:
5102 if (resolve_frame) {
5103 resolve_async_fn_frame(g, fn);
5104 }
5105 return;
5106 default:
5107 zig_unreachable();
5108 }
5109 }
5110 fn->inferred_async_node = inferred_async_none;
5111}
5112
5113static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
5114 ZigType *fn_type = fn->type_entry;
5115 assert(!fn_type->data.fn.is_generic);
5116 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
5117
5118 if (fn->analyzed_executable.begin_scope == nullptr) {
5119 fn->analyzed_executable.begin_scope = &fn->def_scope->base;
5120 }
5121 if (fn->analyzed_executable.source_node == nullptr) {
5122 fn->analyzed_executable.source_node = fn->body_node;
5123 }
5124 size_t backward_branch_count = 0;
5125 size_t backward_branch_quota = max(fn->branch_quota, default_backward_branch_quota);
5126 ZigType *block_return_type = ir_analyze(g, fn->stage1_zir, &fn->analyzed_executable,
5127 &backward_branch_count, &backward_branch_quota,
5128 fn_type_id->return_type, return_type_node, nullptr, fn);
5129 fn->src_implicit_return_type = block_return_type;
5130
5131 if (type_is_invalid(block_return_type) || fn->analyzed_executable.first_err_trace_msg != nullptr) {
5132 assert(g->errors.length > 0);
5133 fn->anal_state = FnAnalStateInvalid;
5134 return;
5135 }
5136
5137 if (fn_type_id->return_type->id == ZigTypeIdErrorUnion) {
5138 ZigType *return_err_set_type = fn_type_id->return_type->data.error_union.err_set_type;
5139 if (return_err_set_type->data.error_set.infer_fn != nullptr &&
5140 return_err_set_type->data.error_set.incomplete)
5141 {
5142 // The inferred error set type is null if the function doesn't
5143 // return any error
5144 ZigType *inferred_err_set_type = nullptr;
5145
5146 if (fn->src_implicit_return_type->id == ZigTypeIdErrorSet) {
5147 inferred_err_set_type = fn->src_implicit_return_type;
5148 } else if (fn->src_implicit_return_type->id == ZigTypeIdErrorUnion) {
5149 inferred_err_set_type = fn->src_implicit_return_type->data.error_union.err_set_type;
5150 }
5151
5152 if (inferred_err_set_type != nullptr) {
5153 if (inferred_err_set_type->data.error_set.infer_fn != nullptr &&
5154 inferred_err_set_type->data.error_set.incomplete)
5155 {
5156 if (!resolve_inferred_error_set(g, inferred_err_set_type, return_type_node)) {
5157 fn->anal_state = FnAnalStateInvalid;
5158 return;
5159 }
5160 }
5161
5162 return_err_set_type->data.error_set.incomplete = false;
5163 if (type_is_global_error_set(inferred_err_set_type)) {
5164 return_err_set_type->data.error_set.err_count = UINT32_MAX;
5165 } else {
5166 return_err_set_type->data.error_set.err_count = inferred_err_set_type->data.error_set.err_count;
5167 if (inferred_err_set_type->data.error_set.err_count > 0) {
5168 return_err_set_type->data.error_set.errors = heap::c_allocator.allocate<ErrorTableEntry *>(inferred_err_set_type->data.error_set.err_count);
5169 for (uint32_t i = 0; i < inferred_err_set_type->data.error_set.err_count; i += 1) {
5170 return_err_set_type->data.error_set.errors[i] = inferred_err_set_type->data.error_set.errors[i];
5171 }
5172 }
5173 }
5174 } else {
5175 return_err_set_type->data.error_set.incomplete = false;
5176 return_err_set_type->data.error_set.err_count = 0;
5177 }
5178 }
5179 }
5180
5181 CallingConvention cc = fn->type_entry->data.fn.fn_type_id.cc;
5182 if (cc != CallingConventionUnspecified && cc != CallingConventionAsync &&
5183 fn->inferred_async_node != nullptr &&
5184 fn->inferred_async_node != inferred_async_checking &&
5185 fn->inferred_async_node != inferred_async_none)
5186 {
5187 ErrorMsg *msg = add_node_error(g, fn->proto_node,
5188 buf_sprintf("function with calling convention '%s' cannot be async",
5189 calling_convention_name(cc)));
5190 add_async_error_notes(g, msg, fn);
5191 fn->anal_state = FnAnalStateInvalid;
5192 }
5193
5194 if (g->verbose_ir) {
5195 fprintf(stderr, "fn %s() { // (analyzed)\n", buf_ptr(&fn->symbol_name));
5196 ir_print_gen(g, stderr, &fn->analyzed_executable, 4);
5197 fprintf(stderr, "}\n");
5198 }
5199 fn->anal_state = FnAnalStateComplete;
5200}
5201
5202static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
5203 assert(fn_table_entry->anal_state != FnAnalStateProbing);
5204 if (fn_table_entry->anal_state != FnAnalStateReady)
5205 return;
5206
5207 fn_table_entry->anal_state = FnAnalStateProbing;
5208 update_progress_display(g);
5209
5210 AstNode *return_type_node = (fn_table_entry->proto_node != nullptr) ?
5211 fn_table_entry->proto_node->data.fn_proto.return_type : fn_table_entry->fndef_scope->base.source_node;
5212
5213 assert(fn_table_entry->fndef_scope);
5214 if (!fn_table_entry->child_scope)
5215 fn_table_entry->child_scope = &fn_table_entry->fndef_scope->base;
5216
5217 if (define_local_param_variables(g, fn_table_entry) != ErrorNone) {
5218 fn_table_entry->anal_state = FnAnalStateInvalid;
5219 return;
5220 }
5221
5222 ZigType *fn_type = fn_table_entry->type_entry;
5223 assert(!fn_type->data.fn.is_generic);
5224
5225 if (!stage1_astgen_fn(g, fn_table_entry)) {
5226 fn_table_entry->anal_state = FnAnalStateInvalid;
5227 return;
5228 }
5229
5230 if (fn_table_entry->stage1_zir->first_err_trace_msg != nullptr) {
5231 fn_table_entry->anal_state = FnAnalStateInvalid;
5232 return;
5233 }
5234
5235 if (g->verbose_ir) {
5236 fprintf(stderr, "\nfn %s() { // (IR)\n", buf_ptr(&fn_table_entry->symbol_name));
5237 ir_print_src(g, stderr, fn_table_entry->stage1_zir, 4);
5238 fprintf(stderr, "}\n");
5239 }
5240
5241 analyze_fn_ir(g, fn_table_entry, return_type_node);
5242}
5243
5244ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Buf *source_code,
5245 SourceKind source_kind)
5246{
5247 Tokenization tokenization = {0};
5248 tokenize(buf_ptr(source_code), &tokenization);
5249
5250 if (tokenization.err) {
5251 ErrorMsg *err = err_msg_create_with_offset(resolved_path, tokenization.err_byte_offset,
5252 buf_ptr(source_code), tokenization.err);
5253
5254 print_err_msg(err, g->err_color);
5255 exit(1);
5256 }
5257
5258 Buf *src_dirname = buf_alloc();
5259 Buf *src_basename = buf_alloc();
5260 os_path_split(resolved_path, src_dirname, src_basename);
5261
5262 Buf noextname = BUF_INIT;
5263 os_path_extname(resolved_path, &noextname, nullptr);
5264
5265 Buf *pkg_root_src_dir = &package->root_src_dir;
5266 Buf resolved_root_src_dir = os_path_resolve(&pkg_root_src_dir, 1);
5267
5268 Buf *namespace_name = buf_create_from_buf(&package->pkg_path);
5269 if (source_kind == SourceKindNonRoot) {
5270 assert(buf_starts_with_buf(resolved_path, &resolved_root_src_dir));
5271 if (buf_len(namespace_name) != 0) {
5272 buf_append_char(namespace_name, NAMESPACE_SEP_CHAR);
5273 }
5274 // The namespace components are obtained from the relative path to the
5275 // source directory
5276 if (buf_len(&noextname) > buf_len(&resolved_root_src_dir)) {
5277 // Skip the trailing separator
5278 buf_append_mem(namespace_name,
5279 buf_ptr(&noextname) + buf_len(&resolved_root_src_dir) + 1,
5280 buf_len(&noextname) - buf_len(&resolved_root_src_dir) - 1);
5281 }
5282 buf_replace(namespace_name, ZIG_OS_SEP_CHAR, NAMESPACE_SEP_CHAR);
5283 }
5284 Buf *bare_name = buf_alloc();
5285 os_path_extname(src_basename, bare_name, nullptr);
5286
5287 RootStruct *root_struct = heap::c_allocator.create<RootStruct>();
5288 root_struct->package = package;
5289 root_struct->source_code = source_code;
5290 root_struct->path = resolved_path;
5291 root_struct->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
5292
5293 assert(tokenization.ids.length == tokenization.locs.length);
5294 size_t token_count = tokenization.ids.length;
5295 root_struct->token_count = token_count;
5296 root_struct->token_ids = g->pass1_arena->allocate<TokenId>(token_count);
5297 memcpy(root_struct->token_ids, tokenization.ids.items, token_count * sizeof(TokenId));
5298 root_struct->token_locs = g->pass1_arena->allocate<TokenLoc>(token_count);
5299 memcpy(root_struct->token_locs, tokenization.locs.items, token_count * sizeof(TokenLoc));
5300
5301 tokenization.ids.deinit();
5302 tokenization.locs.deinit();
5303
5304 ZigType *import_entry = get_root_container_type(g, buf_ptr(namespace_name), bare_name, root_struct);
5305 if (source_kind == SourceKindRoot) {
5306 assert(g->root_import == nullptr);
5307 g->root_import = import_entry;
5308 }
5309 g->import_table.put(resolved_path, import_entry);
5310
5311 AstNode *root_node = ast_parse(source_code, import_entry, g->err_color);
5312 assert(root_node != nullptr);
5313 assert(root_node->type == NodeTypeContainerDecl);
5314 import_entry->data.structure.decl_node = root_node;
5315 import_entry->data.structure.decls_scope->base.source_node = root_node;
5316
5317 for (size_t decl_i = 0; decl_i < root_node->data.container_decl.decls.length; decl_i += 1) {
5318 AstNode *top_level_decl = root_node->data.container_decl.decls.at(decl_i);
5319 scan_decls(g, import_entry->data.structure.decls_scope, top_level_decl);
5320 }
5321
5322 TldContainer *tld_container = heap::c_allocator.create<TldContainer>();
5323 init_tld(&tld_container->base, TldIdContainer, namespace_name, VisibModPub, root_node, nullptr);
5324 tld_container->type_entry = import_entry;
5325 tld_container->decls_scope = import_entry->data.structure.decls_scope;
5326 g->resolve_queue.append(&tld_container->base);
5327
5328 return import_entry;
5329}
5330
5331void semantic_analyze(CodeGen *g) {
5332 while (g->resolve_queue_index < g->resolve_queue.length ||
5333 g->fn_defs_index < g->fn_defs.length)
5334 {
5335 for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) {
5336 Tld *tld = g->resolve_queue.at(g->resolve_queue_index);
5337 g->trace_err = nullptr;
5338 AstNode *source_node = nullptr;
5339 resolve_top_level_decl(g, tld, source_node, false);
5340 }
5341
5342 for (; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {
5343 ZigFn *fn_entry = g->fn_defs.at(g->fn_defs_index);
5344 g->trace_err = nullptr;
5345 analyze_fn_body(g, fn_entry);
5346 }
5347 }
5348
5349 if (g->errors.length != 0) {
5350 return;
5351 }
5352
5353 // second pass over functions for detecting async
5354 for (g->fn_defs_index = 0; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {
5355 ZigFn *fn = g->fn_defs.at(g->fn_defs_index);
5356 g->trace_err = nullptr;
5357 analyze_fn_async(g, fn, true);
5358 if (fn->anal_state == FnAnalStateInvalid)
5359 continue;
5360 if (fn_is_async(fn) && fn->non_async_node != nullptr) {
5361 ErrorMsg *msg = add_node_error(g, fn->proto_node,
5362 buf_sprintf("'%s' cannot be async", buf_ptr(&fn->symbol_name)));
5363 add_error_note(g, msg, fn->non_async_node,
5364 buf_sprintf("required to be non-async here"));
5365 add_async_error_notes(g, msg, fn);
5366 }
5367 }
5368}
5369
5370ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
5371 assert(size_in_bits <= 65535);
5372 TypeId type_id = {};
5373 type_id.id = ZigTypeIdInt;
5374 type_id.data.integer.is_signed = is_signed;
5375 type_id.data.integer.bit_count = size_in_bits;
5376
5377 {
5378 auto entry = g->type_table.maybe_get(type_id);
5379 if (entry)
5380 return entry->value;
5381 }
5382
5383 ZigType *new_entry = make_int_type(g, is_signed, size_in_bits);
5384 g->type_table.put(type_id, new_entry);
5385 return new_entry;
5386}
5387
5388Error is_valid_vector_elem_type(CodeGen *g, ZigType *elem_type, bool *result) {
5389 if (elem_type->id == ZigTypeIdInt ||
5390 elem_type->id == ZigTypeIdFloat ||
5391 elem_type->id == ZigTypeIdBool)
5392 {
5393 *result = true;
5394 return ErrorNone;
5395 }
5396
5397 Error err;
5398 ZigType *ptr_type;
5399 if ((err = get_codegen_ptr_type(g, elem_type, &ptr_type))) return err;
5400 if (ptr_type != nullptr) {
5401 *result = true;
5402 return ErrorNone;
5403 }
5404
5405 *result = false;
5406 return ErrorNone;
5407}
5408
5409ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {
5410 Error err;
5411
5412 bool valid_vector_elem;
5413 if ((err = is_valid_vector_elem_type(g, elem_type, &valid_vector_elem))) {
5414 codegen_report_errors_and_exit(g);
5415 }
5416 assert(valid_vector_elem);
5417
5418 TypeId type_id = {};
5419 type_id.id = ZigTypeIdVector;
5420 type_id.data.vector.len = len;
5421 type_id.data.vector.elem_type = elem_type;
5422
5423 {
5424 auto entry = g->type_table.maybe_get(type_id);
5425 if (entry)
5426 return entry->value;
5427 }
5428
5429 ZigType *entry = new_type_table_entry(ZigTypeIdVector);
5430 if ((len != 0) && type_has_bits(g, elem_type)) {
5431 // Vectors can only be ints, floats, bools, or pointers. ints (inc. bools) and floats have trivially resolvable
5432 // llvm type refs. pointers we will use usize instead.
5433 LLVMTypeRef example_vector_llvm_type;
5434 if (elem_type->id == ZigTypeIdPointer) {
5435 example_vector_llvm_type = LLVMVectorType(g->builtin_types.entry_usize->llvm_type, len);
5436 } else {
5437 example_vector_llvm_type = LLVMVectorType(elem_type->llvm_type, len);
5438 }
5439 assert(example_vector_llvm_type != nullptr);
5440 entry->size_in_bits = elem_type->size_in_bits * len;
5441 entry->abi_size = LLVMABISizeOfType(g->target_data_ref, example_vector_llvm_type);
5442 entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, example_vector_llvm_type);
5443 }
5444 entry->data.vector.len = len;
5445 entry->data.vector.elem_type = elem_type;
5446 entry->data.vector.padding = 0;
5447
5448 buf_resize(&entry->name, 0);
5449 buf_appendf(&entry->name, "@Vector(%u, %s)", len, buf_ptr(&elem_type->name));
5450
5451 g->type_table.put(type_id, entry);
5452 return entry;
5453}
5454
5455ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {
5456 return &g->builtin_types.entry_c_int[c_int_type];
5457}
5458
5459ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type) {
5460 return *get_c_int_type_ptr(g, c_int_type);
5461}
5462
5463bool handle_is_ptr(CodeGen *g, ZigType *type_entry) {
5464 switch (type_entry->id) {
5465 case ZigTypeIdInvalid:
5466 case ZigTypeIdMetaType:
5467 case ZigTypeIdComptimeFloat:
5468 case ZigTypeIdComptimeInt:
5469 case ZigTypeIdEnumLiteral:
5470 case ZigTypeIdUndefined:
5471 case ZigTypeIdNull:
5472 case ZigTypeIdBoundFn:
5473 case ZigTypeIdOpaque:
5474 zig_unreachable();
5475 case ZigTypeIdUnreachable:
5476 case ZigTypeIdVoid:
5477 case ZigTypeIdBool:
5478 case ZigTypeIdInt:
5479 case ZigTypeIdFloat:
5480 case ZigTypeIdPointer:
5481 case ZigTypeIdErrorSet:
5482 case ZigTypeIdFn:
5483 case ZigTypeIdEnum:
5484 case ZigTypeIdVector:
5485 case ZigTypeIdAnyFrame:
5486 return false;
5487 case ZigTypeIdArray:
5488 case ZigTypeIdStruct:
5489 case ZigTypeIdFnFrame:
5490 return type_has_bits(g, type_entry);
5491 case ZigTypeIdErrorUnion:
5492 return type_has_bits(g, type_entry->data.error_union.payload_type);
5493 case ZigTypeIdOptional:
5494 return type_has_bits(g, type_entry->data.maybe.child_type) &&
5495 !type_is_nonnull_ptr(g, type_entry->data.maybe.child_type) &&
5496 type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet;
5497 case ZigTypeIdUnion:
5498 return type_has_bits(g, type_entry) && type_entry->data.unionation.gen_field_count != 0;
5499
5500 }
5501 zig_unreachable();
5502}
5503
5504static const uint32_t HASH_INIT = 0x811c9dc5U;
5505
5506template<typename T>
5507static uint32_t hash_combine(uint32_t hash, const T *value, size_t count = 1) {
5508 // Simple FNV32 hash
5509 size_t len = sizeof(T) * count;
5510 const unsigned char *char_bytes = (const unsigned char*)value;
5511 for (size_t c = 0; c < len; ++c) {
5512 hash ^= char_bytes[c];
5513 hash *= 0x01000193U;
5514 }
5515 return hash;
5516}
5517
5518static uint32_t hash_combine_bigint(uint32_t hash, const BigInt *value) {
5519 return hash_combine(hash, bigint_ptr(value), value->digit_count);
5520}
5521
5522static uint32_t hash_combine_buf(uint32_t hash, const Buf *buf) {
5523 return hash_combine(hash, buf_ptr(buf), buf_len(buf));
5524}
5525
5526uint32_t fn_table_entry_hash(ZigFn* value) {
5527 return hash_combine(HASH_INIT, &value);
5528}
5529
5530bool fn_table_entry_eql(ZigFn *a, ZigFn *b) {
5531 return a == b;
5532}
5533
5534uint32_t fn_type_id_hash(FnTypeId *id) {
5535 uint32_t hash = HASH_INIT;
5536 hash = hash_combine(hash, &id->cc);
5537 hash = hash_combine(hash, &id->is_var_args);
5538 hash = hash_combine(hash, &id->return_type);
5539 hash = hash_combine(hash, &id->alignment);
5540 for (size_t i = 0; i < id->param_count; i += 1) {
5541 FnTypeParamInfo *info = &id->param_info[i];
5542 hash = hash_combine(hash, &info->is_noalias);
5543 hash = hash_combine(hash, &info->type);
5544 }
5545 return hash;
5546}
5547
5548bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
5549 if (a->cc != b->cc ||
5550 a->return_type != b->return_type ||
5551 a->is_var_args != b->is_var_args ||
5552 a->param_count != b->param_count ||
5553 a->alignment != b->alignment)
5554 {
5555 return false;
5556 }
5557 for (size_t i = 0; i < a->param_count; i += 1) {
5558 FnTypeParamInfo *a_param_info = &a->param_info[i];
5559 FnTypeParamInfo *b_param_info = &b->param_info[i];
5560
5561 if (a_param_info->type != b_param_info->type ||
5562 a_param_info->is_noalias != b_param_info->is_noalias)
5563 {
5564 return false;
5565 }
5566 }
5567 return true;
5568}
5569
5570static uint32_t hash_combine_const_val_error_set(uint32_t hash_val, ZigValue *const_val) {
5571 assert(const_val->data.x_err_set != nullptr);
5572 return hash_combine(hash_val, &const_val->data.x_err_set->value);
5573}
5574
5575static uint32_t hash_combine_const_val_ptr(uint32_t hash_val, ZigValue *const_val) {
5576 hash_val = hash_combine(hash_val, &const_val->data.x_ptr.special);
5577 switch (const_val->data.x_ptr.special) {
5578 case ConstPtrSpecialInvalid:
5579 zig_unreachable();
5580 case ConstPtrSpecialRef:
5581 hash_val = hash_combine(hash_val, &const_val->data.x_ptr.data.ref.pointee);
5582 return hash_val;
5583 case ConstPtrSpecialBaseArray:
5584 hash_val = hash_combine(hash_val, &const_val->data.x_ptr.data.base_array.array_val);
5585 hash_val = hash_combine(hash_val, &const_val->data.x_ptr.data.base_array.elem_index);
5586 return hash_val;
5587 case ConstPtrSpecialSubArray:
5588 hash_val = hash_combine(hash_val, &const_val->data.x_ptr.data.base_array.array_val);
5589 hash_val = hash_combine(hash_val, &const_val->data.x_ptr.data.base_array.elem_index);
5590 return hash_val;
5591 case ConstPtrSpecialBaseStruct:
5592 hash_val = hash_combine(hash_val, &const_val->data.x_ptr.data.base_struct.struct_val);
5593 hash_val = hash_combine(hash_val, &const_val->data.x_ptr.data.base_struct.field_index);
5594 return hash_val;
5595 case ConstPtrSpecialBaseErrorUnionCode:
5596 hash_val = hash_combine(hash_val, &const_val->data.x_ptr.data.base_err_union_code.err_union_val);
5597 return hash_val;
5598 case ConstPtrSpecialBaseErrorUnionPayload:
5599 hash_val = hash_combine(hash_val, &const_val->data.x_ptr.data.base_err_union_payload.err_union_val);
5600 return hash_val;
5601 case ConstPtrSpecialBaseOptionalPayload:
5602 hash_val = hash_combine(hash_val, &const_val->data.x_ptr.data.base_optional_payload.optional_val);
5603 return hash_val;
5604 case ConstPtrSpecialHardCodedAddr:
5605 hash_val = hash_combine(hash_val, &const_val->data.x_ptr.data.hard_coded_addr.addr);
5606 return hash_val;
5607 case ConstPtrSpecialFunction:
5608 hash_val = hash_combine(hash_val, &const_val->data.x_ptr.data.fn.fn_entry);
5609 return hash_val;
5610 case ConstPtrSpecialDiscard:
5611 case ConstPtrSpecialNull:
5612 // No fields to hash
5613 return hash_val;
5614 }
5615 zig_unreachable();
5616}
5617
5618static uint32_t hash_combine_const_val(uint32_t hash_val, ZigValue *const_val);
5619static uint32_t hash_combine_const_val_array(uint32_t hash_val, ZigValue *array, size_t len) {
5620 if (array->data.x_array.special == ConstArraySpecialUndef) {
5621 char undef_tag = 56;
5622 return hash_combine(hash_val, &undef_tag);
5623 } else if (array->data.x_array.special == ConstArraySpecialBuf) {
5624 // Hash in a way that is compatible with standard byte arrays
5625 // If any of these asserts fails, the if after this needs to be modified
5626 // to handle the new type in SpecialBuf.
5627 assert(array->type->data.array.child_type->id == ZigTypeIdInt);
5628 assert(array->type->data.array.child_type->data.integral.bit_count == 8);
5629 assert(array->type->data.array.child_type->data.integral.is_signed == false);
5630 const char *buf_pos = buf_ptr(array->data.x_array.data.s_buf);
5631 const char *buf_end = buf_pos + buf_len(array->data.x_array.data.s_buf);
5632 while (buf_pos < buf_end) {
5633 hash_val = hash_combine(hash_val, buf_pos);
5634 buf_pos++;
5635 }
5636 return hash_val;
5637 } else if (array->type->data.array.child_type->id == ZigTypeIdInt &&
5638 array->type->data.array.child_type->data.integral.bit_count == 8 &&
5639 array->type->data.array.child_type->data.integral.is_signed == false) {
5640 // If the type is u8, we hash it as if it's a ConstArraySpecialBuf,
5641 // to maintain compatibility.
5642 ZigValue *elems = array->data.x_array.data.s_none.elements;
5643 for (size_t i = 0; i < len; i += 1) {
5644 ZigValue *value = &elems[i];
5645 assert(value->type == array->type->data.array.child_type);
5646 // N.B. Using char here instead of uint8_t to match the const char*
5647 // returned by buf_ptr.
5648 const char byte_value = (char) bigint_as_u8(&value->data.x_bigint);
5649 hash_val = hash_combine(hash_val, &byte_value);
5650 }
5651 return hash_val;
5652 } else {
5653 ZigValue *elems = array->data.x_array.data.s_none.elements;
5654 for (size_t i = 0; i < len; i += 1) {
5655 hash_val = hash_combine_const_val(hash_val, &elems[i]);
5656 }
5657 return hash_val;
5658 }
5659}
5660static uint32_t hash_combine_const_val(uint32_t hash_val, ZigValue *const_val) {
5661 hash_val = hash_combine(hash_val, &const_val->special);
5662 if (const_val->special == ConstValSpecialUndef) {
5663 return hash_val;
5664 }
5665 assert(const_val->special == ConstValSpecialStatic);
5666 hash_val = hash_combine(hash_val, &const_val->type->id);
5667 switch (const_val->type->id) {
5668 case ZigTypeIdOpaque:
5669 zig_unreachable();
5670 case ZigTypeIdBool:
5671 return hash_combine(hash_val, &const_val->data.x_bool);
5672 case ZigTypeIdMetaType:
5673 return hash_combine(hash_val, &const_val->data.x_type);
5674 case ZigTypeIdInt:
5675 case ZigTypeIdComptimeInt:
5676 return hash_combine_bigint(hash_val, &const_val->data.x_bigint);
5677 case ZigTypeIdEnumLiteral:
5678 return hash_combine_buf(hash_val, const_val->data.x_enum_literal);
5679 case ZigTypeIdEnum:
5680 return hash_combine_bigint(hash_val, &const_val->data.x_enum_tag);
5681 case ZigTypeIdFloat:
5682 hash_val = hash_combine(hash_val, &const_val->type->data.floating.bit_count);
5683 switch (const_val->type->data.floating.bit_count) {
5684 case 16: return hash_combine(hash_val, &const_val->data.x_f16);
5685 case 32: return hash_combine(hash_val, &const_val->data.x_f32);
5686 case 64: return hash_combine(hash_val, &const_val->data.x_f64);
5687 case 80:
5688 hash_val = hash_combine(hash_val, &const_val->data.x_f80.signExp);
5689 return hash_combine(hash_val, &const_val->data.x_f80.signif);
5690 case 128: return hash_combine(hash_val, &const_val->data.x_f128);
5691 default: zig_unreachable();
5692 }
5693 case ZigTypeIdComptimeFloat:
5694 return hash_combine(hash_val, &const_val->data.x_bigfloat.value);
5695 case ZigTypeIdFn:
5696 assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
5697 assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction);
5698 return hash_combine(hash_val, &const_val->data.x_ptr.data.fn.fn_entry);
5699 case ZigTypeIdPointer:
5700 return hash_combine_const_val_ptr(hash_val, const_val);
5701 case ZigTypeIdVoid:
5702 case ZigTypeIdUndefined:
5703 case ZigTypeIdNull:
5704 return hash_val;
5705 case ZigTypeIdArray:
5706 return hash_combine_const_val_array(hash_val, const_val, const_val->type->data.array.len);
5707 case ZigTypeIdStruct: {
5708 size_t field_count = const_val->type->data.structure.src_field_count;
5709 for (size_t i = 0; i < field_count; i += 1) {
5710 if (const_val->type->data.structure.fields[i]->is_comptime) {
5711 // The values of comptime struct fields are part of the
5712 // type, not the value, so they do not participate in equality
5713 // or hash of comptime values.
5714 continue;
5715 }
5716 ZigValue *field = const_val->data.x_struct.fields[i];
5717 hash_val = hash_combine_const_val(hash_val, field);
5718 }
5719 return hash_val;
5720 }
5721 case ZigTypeIdUnion: {
5722 ConstUnionValue *union_value = &const_val->data.x_union;
5723 hash_val = hash_combine_bigint(hash_val, &union_value->tag);
5724 return hash_combine_const_val(hash_val, union_value->payload);
5725 }
5726 case ZigTypeIdOptional:
5727 if (get_src_ptr_type(const_val->type) != nullptr) {
5728 char tag = 1;
5729 hash_val = hash_combine(hash_val, &tag);
5730 return hash_combine_const_val_ptr(hash_val, const_val);
5731 } else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) {
5732 char tag = 2;
5733 hash_val = hash_combine(hash_val, &tag);
5734 return hash_combine_const_val_error_set(hash_val, const_val);
5735 } else if (const_val->data.x_optional) {
5736 char tag = 3;
5737 hash_val = hash_combine(hash_val, &tag);
5738 return hash_combine_const_val(hash_val, const_val->data.x_optional);
5739 } else {
5740 char tag = 4;
5741 hash_val = hash_combine(hash_val, &tag);
5742 return hash_val;
5743 }
5744 case ZigTypeIdErrorUnion: {
5745 bool is_err = const_val->data.x_err_union.error_set->data.x_err_set != nullptr;
5746 hash_val = hash_combine(hash_val, &is_err);
5747 if (is_err) {
5748 hash_val = hash_combine_const_val(hash_val, const_val->data.x_err_union.error_set);
5749 } else {
5750 hash_val = hash_combine_const_val(hash_val, const_val->data.x_err_union.payload);
5751 }
5752 return hash_val;
5753 }
5754 case ZigTypeIdErrorSet:
5755 return hash_combine_const_val_error_set(hash_val, const_val);
5756 case ZigTypeIdVector:
5757 return hash_combine_const_val_array(hash_val, const_val, const_val->type->data.vector.len);
5758 case ZigTypeIdFnFrame:
5759 // TODO better hashing algorithm
5760 return hash_val;
5761 case ZigTypeIdAnyFrame:
5762 // TODO better hashing algorithm
5763 return hash_val;
5764 case ZigTypeIdBoundFn: {
5765 assert(const_val->data.x_bound_fn.fn != nullptr);
5766 return hash_combine(hash_val, &const_val->data.x_bound_fn.fn);
5767 }
5768 case ZigTypeIdInvalid:
5769 case ZigTypeIdUnreachable:
5770 zig_unreachable();
5771 }
5772 zig_unreachable();
5773}
5774
5775uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) {
5776 uint32_t result = HASH_INIT;
5777 result = hash_combine(result, &id->fn_entry);
5778 for (size_t i = 0; i < id->param_count; i += 1) {
5779 ZigValue *generic_param = &id->params[i];
5780 if (generic_param->special != ConstValSpecialRuntime) {
5781 result = hash_combine_const_val(result, generic_param);
5782 result = hash_combine(result, &generic_param->type);
5783 }
5784 }
5785 return result;
5786}
5787
5788bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {
5789 assert(a->fn_entry);
5790 if (a->fn_entry != b->fn_entry) return false;
5791 if (a->param_count != b->param_count) return false;
5792 for (size_t i = 0; i < a->param_count; i += 1) {
5793 ZigValue *a_val = &a->params[i];
5794 ZigValue *b_val = &b->params[i];
5795 if (a_val->type != b_val->type) return false;
5796 if (a_val->special != ConstValSpecialRuntime && b_val->special != ConstValSpecialRuntime) {
5797 assert(a_val->special == ConstValSpecialStatic);
5798 assert(b_val->special == ConstValSpecialStatic);
5799 if (!const_values_equal(a->codegen, a_val, b_val)) {
5800 return false;
5801 }
5802 } else {
5803 assert(a_val->special == ConstValSpecialRuntime && b_val->special == ConstValSpecialRuntime);
5804 }
5805 }
5806 return true;
5807}
5808
5809static bool can_mutate_comptime_var_state(ZigValue *value) {
5810 assert(value != nullptr);
5811 if (value->special == ConstValSpecialUndef)
5812 return false;
5813
5814 if (value->special == ConstValSpecialLazy) {
5815 // No lazy value has side effects.
5816 // Use a switch here to get a compile error whenever a new kind of lazy
5817 // value is added.
5818 switch (value->data.x_lazy->id) {
5819 case LazyValueIdInvalid:
5820 zig_unreachable();
5821
5822 case LazyValueIdAlignOf:
5823 case LazyValueIdSizeOf:
5824 case LazyValueIdPtrType:
5825 case LazyValueIdPtrTypeSimple:
5826 case LazyValueIdPtrTypeSimpleConst:
5827 case LazyValueIdOptType:
5828 case LazyValueIdSliceType:
5829 case LazyValueIdFnType:
5830 case LazyValueIdErrUnionType:
5831 case LazyValueIdArrayType:
5832 case LazyValueIdTypeInfoDecls:
5833 return false;
5834 }
5835 }
5836
5837 switch (value->type->id) {
5838 case ZigTypeIdInvalid:
5839 zig_unreachable();
5840 case ZigTypeIdMetaType:
5841 case ZigTypeIdVoid:
5842 case ZigTypeIdBool:
5843 case ZigTypeIdUnreachable:
5844 case ZigTypeIdInt:
5845 case ZigTypeIdVector:
5846 case ZigTypeIdFloat:
5847 case ZigTypeIdComptimeFloat:
5848 case ZigTypeIdComptimeInt:
5849 case ZigTypeIdEnumLiteral:
5850 case ZigTypeIdUndefined:
5851 case ZigTypeIdNull:
5852 case ZigTypeIdBoundFn:
5853 case ZigTypeIdFn:
5854 case ZigTypeIdOpaque:
5855 case ZigTypeIdErrorSet:
5856 case ZigTypeIdEnum:
5857 case ZigTypeIdFnFrame:
5858 case ZigTypeIdAnyFrame:
5859 return false;
5860
5861 case ZigTypeIdPointer:
5862 return value->data.x_ptr.mut == ConstPtrMutComptimeVar;
5863
5864 case ZigTypeIdArray:
5865 if (value->special == ConstValSpecialUndef)
5866 return false;
5867 if (value->type->data.array.len == 0)
5868 return false;
5869 switch (value->data.x_array.special) {
5870 case ConstArraySpecialUndef:
5871 case ConstArraySpecialBuf:
5872 return false;
5873 case ConstArraySpecialNone:
5874 for (uint32_t i = 0; i < value->type->data.array.len; i += 1) {
5875 if (can_mutate_comptime_var_state(&value->data.x_array.data.s_none.elements[i]))
5876 return true;
5877 }
5878 return false;
5879 }
5880 zig_unreachable();
5881 case ZigTypeIdStruct:
5882 for (uint32_t i = 0; i < value->type->data.structure.src_field_count; i += 1) {
5883 TypeStructField *type_struct_field = value->type->data.structure.fields[i];
5884
5885 ZigValue *field_value = type_struct_field->is_comptime ?
5886 type_struct_field->init_val :
5887 value->data.x_struct.fields[i];
5888
5889 if (can_mutate_comptime_var_state(field_value))
5890 return true;
5891 }
5892 return false;
5893
5894 case ZigTypeIdOptional:
5895 if (get_src_ptr_type(value->type) != nullptr)
5896 return value->data.x_ptr.mut == ConstPtrMutComptimeVar;
5897 if (value->data.x_optional == nullptr)
5898 return false;
5899 return can_mutate_comptime_var_state(value->data.x_optional);
5900
5901 case ZigTypeIdErrorUnion:
5902 if (value->data.x_err_union.error_set->data.x_err_set != nullptr)
5903 return false;
5904 assert(value->data.x_err_union.payload != nullptr);
5905 return can_mutate_comptime_var_state(value->data.x_err_union.payload);
5906
5907 case ZigTypeIdUnion:
5908 return can_mutate_comptime_var_state(value->data.x_union.payload);
5909 }
5910 zig_unreachable();
5911}
5912
5913bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {
5914 while (scope) {
5915 if (scope->id == ScopeIdVarDecl) {
5916 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
5917 if (type_is_invalid(var_scope->var->var_type))
5918 return false;
5919 if (var_scope->var->const_value->special == ConstValSpecialUndef)
5920 return false;
5921 if (can_mutate_comptime_var_state(var_scope->var->const_value))
5922 return false;
5923 } else if (scope->id == ScopeIdFnDef) {
5924 return true;
5925 } else {
5926 zig_unreachable();
5927 }
5928
5929 scope = scope->parent;
5930 }
5931 zig_unreachable();
5932}
5933
5934uint32_t fn_eval_hash(Scope* scope) {
5935 uint32_t hash = HASH_INIT;
5936 while (scope) {
5937 if (scope->id == ScopeIdVarDecl) {
5938 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
5939 hash = hash_combine_const_val(hash, var_scope->var->const_value);
5940 } else if (scope->id == ScopeIdFnDef) {
5941 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
5942 hash = hash_combine(hash, &fn_scope->fn_entry);
5943 return hash;
5944 } else {
5945 zig_unreachable();
5946 }
5947
5948 scope = scope->parent;
5949 }
5950 zig_unreachable();
5951}
5952
5953bool fn_eval_eql(Scope *a, Scope *b) {
5954 assert(a->codegen != nullptr);
5955 assert(b->codegen != nullptr);
5956 while (a && b) {
5957 if (a->id != b->id)
5958 return false;
5959
5960 if (a->id == ScopeIdVarDecl) {
5961 ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a;
5962 ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b;
5963 if (a_var_scope->var->var_type != b_var_scope->var->var_type)
5964 return false;
5965 if (a_var_scope->var->var_type == a_var_scope->var->const_value->type &&
5966 b_var_scope->var->var_type == b_var_scope->var->const_value->type)
5967 {
5968 if (!const_values_equal(a->codegen, a_var_scope->var->const_value, b_var_scope->var->const_value))
5969 return false;
5970 } else {
5971 zig_panic("TODO comptime ptr reinterpret for fn_eval_eql");
5972 }
5973 } else if (a->id == ScopeIdFnDef) {
5974 ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;
5975 ScopeFnDef *b_fn_scope = (ScopeFnDef *)b;
5976 if (a_fn_scope->fn_entry != b_fn_scope->fn_entry)
5977 return false;
5978
5979 return true;
5980 } else {
5981 zig_unreachable();
5982 }
5983
5984 a = a->parent;
5985 b = b->parent;
5986 }
5987 return false;
5988}
5989
5990// Deprecated. Use type_has_bits2.
5991bool type_has_bits(CodeGen *g, ZigType *type_entry) {
5992 Error err;
5993 bool result;
5994 if ((err = type_has_bits2(g, type_entry, &result))) {
5995 codegen_report_errors_and_exit(g);
5996 }
5997 return result;
5998}
5999
6000// Whether the type has bits at runtime.
6001Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result) {
6002 Error err;
6003
6004 if (type_is_invalid(type_entry))
6005 return ErrorSemanticAnalyzeFail;
6006
6007 if (type_entry->id == ZigTypeIdStruct &&
6008 type_entry->data.structure.resolve_status == ResolveStatusBeingInferred)
6009 {
6010 *result = true;
6011 return ErrorNone;
6012 }
6013
6014 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
6015 return err;
6016
6017 *result = type_entry->abi_size != 0;
6018 return ErrorNone;
6019}
6020
6021bool fn_returns_c_abi_small_struct(FnTypeId *fn_type_id) {
6022 ZigType *type = fn_type_id->return_type;
6023 return !calling_convention_allows_zig_types(fn_type_id->cc) &&
6024 type->id == ZigTypeIdStruct && type->abi_size <= 16;
6025}
6026
6027// Whether you can infer the value based solely on the type.
6028OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
6029 assert(type_entry != nullptr);
6030
6031 if (type_entry->one_possible_value != OnePossibleValueInvalid)
6032 return type_entry->one_possible_value;
6033
6034 if (type_entry->id == ZigTypeIdStruct &&
6035 type_entry->data.structure.resolve_status == ResolveStatusBeingInferred)
6036 {
6037 return OnePossibleValueNo;
6038 }
6039
6040 Error err;
6041 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
6042 return OnePossibleValueInvalid;
6043 switch (type_entry->id) {
6044 case ZigTypeIdInvalid:
6045 zig_unreachable();
6046 case ZigTypeIdOpaque:
6047 case ZigTypeIdComptimeFloat:
6048 case ZigTypeIdComptimeInt:
6049 case ZigTypeIdEnumLiteral:
6050 case ZigTypeIdMetaType:
6051 case ZigTypeIdBoundFn:
6052 case ZigTypeIdOptional:
6053 case ZigTypeIdFn:
6054 case ZigTypeIdBool:
6055 case ZigTypeIdFloat:
6056 case ZigTypeIdErrorUnion:
6057 case ZigTypeIdFnFrame:
6058 case ZigTypeIdAnyFrame:
6059 return OnePossibleValueNo;
6060 case ZigTypeIdUndefined:
6061 case ZigTypeIdNull:
6062 case ZigTypeIdVoid:
6063 case ZigTypeIdUnreachable:
6064 return OnePossibleValueYes;
6065 case ZigTypeIdArray:
6066 if (type_entry->data.array.len == 0)
6067 return OnePossibleValueYes;
6068 return type_has_one_possible_value(g, type_entry->data.array.child_type);
6069 case ZigTypeIdStruct:
6070 // If the recursive function call asks, then we are not one possible value.
6071 type_entry->one_possible_value = OnePossibleValueNo;
6072 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
6073 TypeStructField *field = type_entry->data.structure.fields[i];
6074 if (field->is_comptime) {
6075 // If this field is comptime then the field can only be one possible value
6076 continue;
6077 }
6078 OnePossibleValue opv = (field->type_entry != nullptr) ?
6079 type_has_one_possible_value(g, field->type_entry) :
6080 type_val_resolve_has_one_possible_value(g, field->type_val);
6081 switch (opv) {
6082 case OnePossibleValueInvalid:
6083 type_entry->one_possible_value = OnePossibleValueInvalid;
6084 return OnePossibleValueInvalid;
6085 case OnePossibleValueNo:
6086 return OnePossibleValueNo;
6087 case OnePossibleValueYes:
6088 continue;
6089 }
6090 }
6091 type_entry->one_possible_value = OnePossibleValueYes;
6092 return OnePossibleValueYes;
6093 case ZigTypeIdErrorSet:
6094 case ZigTypeIdEnum:
6095 case ZigTypeIdInt:
6096 case ZigTypeIdVector:
6097 return type_has_bits(g, type_entry) ? OnePossibleValueNo : OnePossibleValueYes;
6098 case ZigTypeIdPointer: {
6099 ZigType *elem_type = type_entry->data.pointer.child_type;
6100 // If the recursive function call asks, then we are not one possible value.
6101 type_entry->one_possible_value = OnePossibleValueNo;
6102 // Now update it to be the value of the recursive call.
6103 type_entry->one_possible_value = type_has_one_possible_value(g, elem_type);
6104 return type_entry->one_possible_value;
6105 }
6106 case ZigTypeIdUnion:
6107 if (type_entry->data.unionation.src_field_count > 1)
6108 return OnePossibleValueNo;
6109 TypeUnionField *only_field = &type_entry->data.unionation.fields[0];
6110 if (only_field->type_entry != nullptr) {
6111 return type_has_one_possible_value(g, only_field->type_entry);
6112 }
6113 return type_val_resolve_has_one_possible_value(g, only_field->type_val);
6114 }
6115 zig_unreachable();
6116}
6117
6118ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
6119 auto entry = g->one_possible_values.maybe_get(type_entry);
6120 if (entry != nullptr) {
6121 return entry->value;
6122 }
6123 ZigValue *result = g->pass1_arena->create<ZigValue>();
6124 result->type = type_entry;
6125 result->special = ConstValSpecialStatic;
6126
6127 if (result->type->id == ZigTypeIdStruct) {
6128 // The fields array cannot be left unpopulated
6129 const ZigType *struct_type = result->type;
6130 const size_t field_count = struct_type->data.structure.src_field_count;
6131 result->data.x_struct.fields = alloc_const_vals_ptrs(g, field_count);
6132 for (size_t i = 0; i < field_count; i += 1) {
6133 TypeStructField *field = struct_type->data.structure.fields[i];
6134 if (field->is_comptime) {
6135 // Comptime fields are part of the type, and do not need to
6136 // be initialized.
6137 continue;
6138 }
6139 ZigType *field_type = resolve_struct_field_type(g, field);
6140 assert(field_type != nullptr);
6141 copy_const_val(g, result->data.x_struct.fields[i],
6142 get_the_one_possible_value(g, field_type));
6143 }
6144 } else if (result->type->id == ZigTypeIdArray) {
6145 // The elements array cannot be left unpopulated
6146 ZigType *array_type = result->type;
6147 ZigType *elem_type = array_type->data.array.child_type;
6148 const size_t elem_count = array_type->data.array.len;
6149
6150 result->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(elem_count);
6151 for (size_t i = 0; i < elem_count; i += 1) {
6152 ZigValue *elem_val = &result->data.x_array.data.s_none.elements[i];
6153 copy_const_val(g, elem_val, get_the_one_possible_value(g, elem_type));
6154 }
6155 } else if (result->type->id == ZigTypeIdUnion) {
6156 // The payload/tag fields cannot be left unpopulated
6157 ZigType *union_type = result->type;
6158 assert(union_type->data.unionation.src_field_count == 1);
6159 TypeUnionField *only_field = &union_type->data.unionation.fields[0];
6160 ZigType *field_type = resolve_union_field_type(g, only_field);
6161 assert(field_type);
6162 bigint_init_bigint(&result->data.x_union.tag, &only_field->enum_field->value);
6163 result->data.x_union.payload = g->pass1_arena->create<ZigValue>();
6164 copy_const_val(g, result->data.x_union.payload,
6165 get_the_one_possible_value(g, field_type));
6166 } else if (result->type->id == ZigTypeIdPointer) {
6167 // Make sure nobody can modify the constant value
6168 result->data.x_ptr.mut = ConstPtrMutComptimeConst;
6169 result->data.x_ptr.special = ConstPtrSpecialRef;
6170 result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);
6171 } else if (result->type->id == ZigTypeIdEnum) {
6172 ZigType *enum_type = result->type;
6173 assert(enum_type->data.enumeration.src_field_count == 1);
6174 TypeEnumField *only_field = &result->type->data.enumeration.fields[0];
6175 bigint_init_bigint(&result->data.x_enum_tag, &only_field->value);
6176 }
6177 g->one_possible_values.put(type_entry, result);
6178 return result;
6179}
6180
6181ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) {
6182 Error err;
6183 if (ty == g->builtin_types.entry_anytype) {
6184 return ReqCompTimeYes;
6185 }
6186 switch (ty->id) {
6187 case ZigTypeIdInvalid:
6188 zig_unreachable();
6189 case ZigTypeIdComptimeFloat:
6190 case ZigTypeIdComptimeInt:
6191 case ZigTypeIdEnumLiteral:
6192 case ZigTypeIdUndefined:
6193 case ZigTypeIdNull:
6194 case ZigTypeIdMetaType:
6195 case ZigTypeIdBoundFn:
6196 return ReqCompTimeYes;
6197 case ZigTypeIdArray:
6198 return type_requires_comptime(g, ty->data.array.child_type);
6199 case ZigTypeIdStruct:
6200 if (ty->data.structure.resolve_loop_flag_zero_bits) {
6201 // Does a struct which contains a pointer field to itself require comptime? No.
6202 return ReqCompTimeNo;
6203 }
6204 if ((err = type_resolve(g, ty, ResolveStatusZeroBitsKnown)))
6205 return ReqCompTimeInvalid;
6206 return ty->data.structure.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;
6207 case ZigTypeIdUnion:
6208 if (ty->data.unionation.resolve_loop_flag_zero_bits) {
6209 // Does a union which contains a pointer field to itself require comptime? No.
6210 return ReqCompTimeNo;
6211 }
6212 if ((err = type_resolve(g, ty, ResolveStatusZeroBitsKnown)))
6213 return ReqCompTimeInvalid;
6214 return ty->data.unionation.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;
6215 case ZigTypeIdOptional:
6216 return type_requires_comptime(g, ty->data.maybe.child_type);
6217 case ZigTypeIdErrorUnion:
6218 return type_requires_comptime(g, ty->data.error_union.payload_type);
6219 case ZigTypeIdPointer:
6220 if (ty->data.pointer.child_type->id == ZigTypeIdOpaque) {
6221 return ReqCompTimeNo;
6222 } else {
6223 return type_requires_comptime(g, ty->data.pointer.child_type);
6224 }
6225 case ZigTypeIdFn:
6226 return ty->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo;
6227 case ZigTypeIdOpaque:
6228 case ZigTypeIdEnum:
6229 case ZigTypeIdErrorSet:
6230 case ZigTypeIdBool:
6231 case ZigTypeIdInt:
6232 case ZigTypeIdVector:
6233 case ZigTypeIdFloat:
6234 case ZigTypeIdVoid:
6235 case ZigTypeIdUnreachable:
6236 case ZigTypeIdFnFrame:
6237 case ZigTypeIdAnyFrame:
6238 return ReqCompTimeNo;
6239 }
6240 zig_unreachable();
6241}
6242
6243void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str, bool move_str) {
6244 auto entry = g->string_literals_table.maybe_get(str);
6245 if (entry != nullptr) {
6246 if (move_str) {
6247 buf_destroy(str);
6248 }
6249 memcpy(const_val, entry->value, sizeof(ZigValue));
6250 return;
6251 }
6252
6253 // first we build the underlying array
6254 ZigValue *array_val = g->pass1_arena->create<ZigValue>();
6255 array_val->special = ConstValSpecialStatic;
6256 array_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), g->intern.for_zero_byte());
6257 array_val->data.x_array.special = ConstArraySpecialBuf;
6258 array_val->data.x_array.data.s_buf = str;
6259
6260 // then make the pointer point to it
6261 const_val->special = ConstValSpecialStatic;
6262 const_val->type = get_pointer_to_type_extra2(g, array_val->type, true, false,
6263 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, nullptr);
6264 const_val->data.x_ptr.special = ConstPtrSpecialRef;
6265 const_val->data.x_ptr.data.ref.pointee = array_val;
6266
6267 g->string_literals_table.put(str, const_val);
6268}
6269
6270ZigValue *create_const_str_lit(CodeGen *g, Buf *str) {
6271 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6272 init_const_str_lit(g, const_val, str, false);
6273 return const_val;
6274}
6275
6276ZigValue *create_sentineled_str_lit(CodeGen *g, Buf *str, ZigValue *sentinel) {
6277 ZigValue *array_val = create_const_str_lit(g, str)->data.x_ptr.data.ref.pointee;
6278 return create_const_slice(g, array_val, 0, buf_len(str), true, sentinel);
6279}
6280
6281void init_const_bigint(ZigValue *const_val, ZigType *type, const BigInt *bigint) {
6282 const_val->special = ConstValSpecialStatic;
6283 const_val->type = type;
6284 bigint_init_bigint(&const_val->data.x_bigint, bigint);
6285}
6286
6287ZigValue *create_const_bigint(CodeGen *g, ZigType *type, const BigInt *bigint) {
6288 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6289 init_const_bigint(const_val, type, bigint);
6290 return const_val;
6291}
6292
6293
6294void init_const_unsigned_negative(ZigValue *const_val, ZigType *type, uint64_t x, bool negative) {
6295 const_val->special = ConstValSpecialStatic;
6296 const_val->type = type;
6297 bigint_init_unsigned(&const_val->data.x_bigint, x);
6298 const_val->data.x_bigint.is_negative = negative;
6299}
6300
6301ZigValue *create_const_unsigned_negative(CodeGen *g, ZigType *type, uint64_t x, bool negative) {
6302 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6303 init_const_unsigned_negative(const_val, type, x, negative);
6304 return const_val;
6305}
6306
6307void init_const_usize(CodeGen *g, ZigValue *const_val, uint64_t x) {
6308 return init_const_unsigned_negative(const_val, g->builtin_types.entry_usize, x, false);
6309}
6310
6311ZigValue *create_const_usize(CodeGen *g, uint64_t x) {
6312 return create_const_unsigned_negative(g, g->builtin_types.entry_usize, x, false);
6313}
6314
6315void init_const_signed(ZigValue *const_val, ZigType *type, int64_t x) {
6316 const_val->special = ConstValSpecialStatic;
6317 const_val->type = type;
6318 bigint_init_signed(&const_val->data.x_bigint, x);
6319}
6320
6321ZigValue *create_const_signed(CodeGen *g, ZigType *type, int64_t x) {
6322 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6323 init_const_signed(const_val, type, x);
6324 return const_val;
6325}
6326
6327void init_const_null(ZigValue *const_val, ZigType *type) {
6328 const_val->special = ConstValSpecialStatic;
6329 const_val->type = type;
6330 const_val->data.x_optional = nullptr;
6331}
6332
6333ZigValue *create_const_null(CodeGen *g, ZigType *type) {
6334 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6335 init_const_null(const_val, type);
6336 return const_val;
6337}
6338
6339void init_const_fn(ZigValue *const_val, ZigFn *fn) {
6340 const_val->special = ConstValSpecialStatic;
6341 const_val->type = fn->type_entry;
6342 const_val->data.x_ptr.special = ConstPtrSpecialFunction;
6343 const_val->data.x_ptr.data.fn.fn_entry = fn;
6344}
6345
6346ZigValue *create_const_fn(CodeGen *g, ZigFn *fn) {
6347 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6348 init_const_fn(const_val, fn);
6349 return const_val;
6350}
6351
6352void init_const_float(ZigValue *const_val, ZigType *type, double value) {
6353 const_val->special = ConstValSpecialStatic;
6354 const_val->type = type;
6355 if (type->id == ZigTypeIdComptimeFloat) {
6356 bigfloat_init_64(&const_val->data.x_bigfloat, value);
6357 } else if (type->id == ZigTypeIdFloat) {
6358 switch (type->data.floating.bit_count) {
6359 case 16:
6360 const_val->data.x_f16 = zig_double_to_f16(value);
6361 break;
6362 case 32:
6363 const_val->data.x_f32 = value;
6364 break;
6365 case 64:
6366 const_val->data.x_f64 = value;
6367 break;
6368 case 80:
6369 zig_double_to_extF80M(value, &const_val->data.x_f80);
6370 break;
6371 case 128:
6372 zig_double_to_f128M(value, &const_val->data.x_f128);
6373 break;
6374 default:
6375 zig_unreachable();
6376 }
6377 } else {
6378 zig_unreachable();
6379 }
6380}
6381
6382ZigValue *create_const_float(CodeGen *g, ZigType *type, double value) {
6383 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6384 init_const_float(const_val, type, value);
6385 return const_val;
6386}
6387
6388void init_const_enum(ZigValue *const_val, ZigType *type, const BigInt *tag) {
6389 const_val->special = ConstValSpecialStatic;
6390 const_val->type = type;
6391 bigint_init_bigint(&const_val->data.x_enum_tag, tag);
6392}
6393
6394ZigValue *create_const_enum(CodeGen *g, ZigType *type, const BigInt *tag) {
6395 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6396 init_const_enum(const_val, type, tag);
6397 return const_val;
6398}
6399
6400
6401void init_const_bool(CodeGen *g, ZigValue *const_val, bool value) {
6402 const_val->special = ConstValSpecialStatic;
6403 const_val->type = g->builtin_types.entry_bool;
6404 const_val->data.x_bool = value;
6405}
6406
6407ZigValue *create_const_bool(CodeGen *g, bool value) {
6408 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6409 init_const_bool(g, const_val, value);
6410 return const_val;
6411}
6412
6413void init_const_runtime(ZigValue *const_val, ZigType *type) {
6414 const_val->special = ConstValSpecialRuntime;
6415 const_val->type = type;
6416}
6417
6418ZigValue *create_const_runtime(CodeGen *g, ZigType *type) {
6419 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6420 init_const_runtime(const_val, type);
6421 return const_val;
6422}
6423
6424void init_const_type(CodeGen *g, ZigValue *const_val, ZigType *type_value) {
6425 const_val->special = ConstValSpecialStatic;
6426 const_val->type = g->builtin_types.entry_type;
6427 const_val->data.x_type = type_value;
6428}
6429
6430ZigValue *create_const_type(CodeGen *g, ZigType *type_value) {
6431 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6432 init_const_type(g, const_val, type_value);
6433 return const_val;
6434}
6435
6436void init_const_slice(CodeGen *g, ZigValue *const_val, ZigValue *array_val,
6437 size_t start, size_t len, bool is_const, ZigValue *sentinel)
6438{
6439 assert(array_val->type->id == ZigTypeIdArray);
6440
6441 ZigType *ptr_type = get_pointer_to_type_extra2(g, array_val->type->data.array.child_type,
6442 is_const, false, PtrLenUnknown, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, sentinel);
6443
6444 const_val->special = ConstValSpecialStatic;
6445 const_val->type = get_slice_type(g, ptr_type);
6446 const_val->data.x_struct.fields = alloc_const_vals_ptrs(g, 2);
6447
6448 init_const_ptr_array(g, const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const,
6449 PtrLenUnknown);
6450 init_const_usize(g, const_val->data.x_struct.fields[slice_len_index], len);
6451}
6452
6453ZigValue *create_const_slice(CodeGen *g, ZigValue *array_val, size_t start, size_t len, bool is_const, ZigValue *sentinel) {
6454 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6455 init_const_slice(g, const_val, array_val, start, len, is_const, sentinel);
6456 return const_val;
6457}
6458
6459void init_const_ptr_array(CodeGen *g, ZigValue *const_val, ZigValue *array_val,
6460 size_t elem_index, bool is_const, PtrLen ptr_len)
6461{
6462 assert(array_val->type->id == ZigTypeIdArray);
6463 ZigType *child_type = array_val->type->data.array.child_type;
6464
6465 const_val->special = ConstValSpecialStatic;
6466 const_val->type = get_pointer_to_type_extra(g, child_type, is_const, false,
6467 ptr_len, 0, 0, 0, false);
6468 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
6469 const_val->data.x_ptr.data.base_array.array_val = array_val;
6470 const_val->data.x_ptr.data.base_array.elem_index = elem_index;
6471}
6472
6473ZigValue *create_const_ptr_array(CodeGen *g, ZigValue *array_val, size_t elem_index, bool is_const,
6474 PtrLen ptr_len)
6475{
6476 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6477 init_const_ptr_array(g, const_val, array_val, elem_index, is_const, ptr_len);
6478 return const_val;
6479}
6480
6481void init_const_ptr_ref(CodeGen *g, ZigValue *const_val, ZigValue *pointee_val, bool is_const) {
6482 const_val->special = ConstValSpecialStatic;
6483 const_val->type = get_pointer_to_type(g, pointee_val->type, is_const);
6484 const_val->data.x_ptr.special = ConstPtrSpecialRef;
6485 const_val->data.x_ptr.data.ref.pointee = pointee_val;
6486}
6487
6488ZigValue *create_const_ptr_ref(CodeGen *g, ZigValue *pointee_val, bool is_const) {
6489 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6490 init_const_ptr_ref(g, const_val, pointee_val, is_const);
6491 return const_val;
6492}
6493
6494void init_const_ptr_hard_coded_addr(CodeGen *g, ZigValue *const_val, ZigType *pointee_type,
6495 size_t addr, bool is_const)
6496{
6497 const_val->special = ConstValSpecialStatic;
6498 const_val->type = get_pointer_to_type(g, pointee_type, is_const);
6499 const_val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
6500 const_val->data.x_ptr.data.hard_coded_addr.addr = addr;
6501}
6502
6503ZigValue *create_const_ptr_hard_coded_addr(CodeGen *g, ZigType *pointee_type,
6504 size_t addr, bool is_const)
6505{
6506 ZigValue *const_val = g->pass1_arena->create<ZigValue>();
6507 init_const_ptr_hard_coded_addr(g, const_val, pointee_type, addr, is_const);
6508 return const_val;
6509}
6510
6511ZigValue **alloc_const_vals_ptrs(CodeGen *g, size_t count) {
6512 return realloc_const_vals_ptrs(g, nullptr, 0, count);
6513}
6514
6515ZigValue **realloc_const_vals_ptrs(CodeGen *g, ZigValue **ptr, size_t old_count, size_t new_count) {
6516 assert(new_count >= old_count);
6517
6518 size_t new_item_count = new_count - old_count;
6519 ZigValue **result = heap::c_allocator.reallocate(ptr, old_count, new_count);
6520 ZigValue *vals = g->pass1_arena->allocate<ZigValue>(new_item_count);
6521 for (size_t i = old_count; i < new_count; i += 1) {
6522 result[i] = &vals[i - old_count];
6523 }
6524 return result;
6525}
6526
6527TypeStructField **alloc_type_struct_fields(size_t count) {
6528 return realloc_type_struct_fields(nullptr, 0, count);
6529}
6530
6531TypeStructField **realloc_type_struct_fields(TypeStructField **ptr, size_t old_count, size_t new_count) {
6532 assert(new_count >= old_count);
6533
6534 size_t new_item_count = new_count - old_count;
6535 TypeStructField **result = heap::c_allocator.reallocate(ptr, old_count, new_count);
6536 TypeStructField *vals = heap::c_allocator.allocate<TypeStructField>(new_item_count);
6537 for (size_t i = old_count; i < new_count; i += 1) {
6538 result[i] = &vals[i - old_count];
6539 }
6540 return result;
6541}
6542
6543static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {
6544 if (orig_fn_type->data.fn.fn_type_id.cc == CallingConventionAsync)
6545 return orig_fn_type;
6546
6547 ZigType *fn_type = heap::c_allocator.allocate_nonzero<ZigType>(1);
6548 *fn_type = *orig_fn_type;
6549 fn_type->data.fn.fn_type_id.cc = CallingConventionAsync;
6550 fn_type->llvm_type = nullptr;
6551 fn_type->llvm_di_type = nullptr;
6552
6553 return fn_type;
6554}
6555
6556// Traverse up to the very top ExprScope, which has children.
6557// We have just arrived at the top from a child. That child,
6558// and its next siblings, do not need to be marked. But the previous
6559// siblings do.
6560// x + (await y)
6561// vs
6562// (await y) + x
6563static void mark_suspension_point(Scope *scope) {
6564 ScopeExpr *child_expr_scope = (scope->id == ScopeIdExpr) ? reinterpret_cast<ScopeExpr *>(scope) : nullptr;
6565 bool looking_for_exprs = true;
6566 for (;;) {
6567 scope = scope->parent;
6568 switch (scope->id) {
6569 case ScopeIdDeferExpr:
6570 case ScopeIdDecls:
6571 case ScopeIdFnDef:
6572 case ScopeIdCompTime:
6573 case ScopeIdNoSuspend:
6574 case ScopeIdCImport:
6575 case ScopeIdSuspend:
6576 case ScopeIdTypeOf:
6577 return;
6578 case ScopeIdVarDecl:
6579 case ScopeIdDefer:
6580 case ScopeIdBlock:
6581 looking_for_exprs = false;
6582 continue;
6583 case ScopeIdRuntime:
6584 continue;
6585 case ScopeIdLoop: {
6586 ScopeLoop *loop_scope = reinterpret_cast<ScopeLoop *>(scope);
6587 if (loop_scope->spill_scope != nullptr) {
6588 loop_scope->spill_scope->need_spill = MemoizedBoolTrue;
6589 }
6590 looking_for_exprs = false;
6591 continue;
6592 }
6593 case ScopeIdExpr: {
6594 ScopeExpr *parent_expr_scope = reinterpret_cast<ScopeExpr *>(scope);
6595 if (!looking_for_exprs) {
6596 if (parent_expr_scope->spill_harder) {
6597 parent_expr_scope->need_spill = MemoizedBoolTrue;
6598 }
6599 // Now we're only looking for a block, to see if it's in a loop (see the case ScopeIdBlock)
6600 continue;
6601 }
6602 if (child_expr_scope != nullptr) {
6603 for (size_t i = 0; parent_expr_scope->children_ptr[i] != child_expr_scope; i += 1) {
6604 assert(i < parent_expr_scope->children_len);
6605 parent_expr_scope->children_ptr[i]->need_spill = MemoizedBoolTrue;
6606 }
6607 }
6608 parent_expr_scope->need_spill = MemoizedBoolTrue;
6609 child_expr_scope = parent_expr_scope;
6610 continue;
6611 }
6612 }
6613 }
6614}
6615
6616static bool scope_needs_spill(Scope *scope) {
6617 ScopeExpr *scope_expr = find_expr_scope(scope);
6618 if (scope_expr == nullptr) return false;
6619
6620 switch (scope_expr->need_spill) {
6621 case MemoizedBoolUnknown:
6622 if (scope_needs_spill(scope_expr->base.parent)) {
6623 scope_expr->need_spill = MemoizedBoolTrue;
6624 return true;
6625 } else {
6626 scope_expr->need_spill = MemoizedBoolFalse;
6627 return false;
6628 }
6629 case MemoizedBoolFalse:
6630 return false;
6631 case MemoizedBoolTrue:
6632 return true;
6633 }
6634 zig_unreachable();
6635}
6636
6637static ZigType *resolve_type_isf(ZigType *ty) {
6638 if (ty->id != ZigTypeIdPointer) return ty;
6639 InferredStructField *isf = ty->data.pointer.inferred_struct_field;
6640 if (isf == nullptr) return ty;
6641 TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
6642 assert(field != nullptr);
6643 return field->type_entry;
6644}
6645
6646static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
6647 Error err;
6648
6649 if (frame_type->data.frame.locals_struct != nullptr)
6650 return ErrorNone;
6651
6652 ZigFn *fn = frame_type->data.frame.fn;
6653 assert(!fn->type_entry->data.fn.is_generic);
6654
6655 if (frame_type->data.frame.resolve_loop_type != nullptr) {
6656 if (!frame_type->data.frame.reported_loop_err) {
6657 add_node_error(g, fn->proto_node,
6658 buf_sprintf("'%s' depends on itself", buf_ptr(&frame_type->name)));
6659 }
6660 return ErrorSemanticAnalyzeFail;
6661 }
6662
6663 switch (fn->anal_state) {
6664 case FnAnalStateInvalid:
6665 return ErrorSemanticAnalyzeFail;
6666 case FnAnalStateComplete:
6667 break;
6668 case FnAnalStateReady:
6669 analyze_fn_body(g, fn);
6670 if (fn->anal_state == FnAnalStateInvalid)
6671 return ErrorSemanticAnalyzeFail;
6672 break;
6673 case FnAnalStateProbing: {
6674 add_node_error(g, fn->proto_node,
6675 buf_sprintf("cannot resolve '%s': function not fully analyzed yet",
6676 buf_ptr(&frame_type->name)));
6677 return ErrorSemanticAnalyzeFail;
6678 }
6679 }
6680 analyze_fn_async(g, fn, false);
6681 if (fn->anal_state == FnAnalStateInvalid)
6682 return ErrorSemanticAnalyzeFail;
6683
6684 if (!fn_is_async(fn)) {
6685 ZigType *fn_type = fn->type_entry;
6686 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
6687 ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false);
6688
6689 // label (grep this): [fn_frame_struct_layout]
6690 ZigList<SrcField> fields = {};
6691
6692 fields.append({"@fn_ptr", g->builtin_types.entry_usize, 0});
6693 fields.append({"@resume_index", g->builtin_types.entry_usize, 0});
6694 fields.append({"@awaiter", g->builtin_types.entry_usize, 0});
6695
6696 fields.append({"@result_ptr_callee", ptr_return_type, 0});
6697 fields.append({"@result_ptr_awaiter", ptr_return_type, 0});
6698 fields.append({"@result", fn_type_id->return_type, 0});
6699
6700 if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) {
6701 ZigType *ptr_to_stack_trace_type = get_pointer_to_type(g, get_stack_trace_type(g), false);
6702 fields.append({"@ptr_stack_trace_callee", ptr_to_stack_trace_type, 0});
6703 fields.append({"@ptr_stack_trace_awaiter", ptr_to_stack_trace_type, 0});
6704
6705 fields.append({"@stack_trace", get_stack_trace_type(g), 0});
6706 fields.append({"@instruction_addresses",
6707 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, nullptr), 0});
6708 }
6709
6710 frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),
6711 fields.items, fields.length, target_fn_align(g->zig_target));
6712 frame_type->abi_size = frame_type->data.frame.locals_struct->abi_size;
6713 frame_type->abi_align = frame_type->data.frame.locals_struct->abi_align;
6714 frame_type->size_in_bits = frame_type->data.frame.locals_struct->size_in_bits;
6715
6716 return ErrorNone;
6717 }
6718
6719 ZigType *fn_type = get_async_fn_type(g, fn->type_entry);
6720
6721 if (fn->analyzed_executable.need_err_code_spill) {
6722 Stage1AirInstAlloca *alloca_gen = heap::c_allocator.create<Stage1AirInstAlloca>();
6723 alloca_gen->base.id = Stage1AirInstIdAlloca;
6724 alloca_gen->base.source_node = fn->proto_node;
6725 alloca_gen->base.scope = fn->child_scope;
6726 alloca_gen->base.value = g->pass1_arena->create<ZigValue>();
6727 alloca_gen->base.value->type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false);
6728 alloca_gen->base.ref_count = 1;
6729 alloca_gen->name_hint = "";
6730 fn->alloca_gen_list.append(alloca_gen);
6731 fn->err_code_spill = &alloca_gen->base;
6732 }
6733
6734 ZigType *largest_call_frame_type = nullptr;
6735 // Later we'll change this to be largest_call_frame_type instead of void.
6736 Stage1AirInst *all_calls_alloca = ir_create_alloca(g, &fn->fndef_scope->base, fn->body_node,
6737 fn, g->builtin_types.entry_void, "@async_call_frame");
6738
6739 for (size_t i = 0; i < fn->call_list.length; i += 1) {
6740 Stage1AirInstCall *call = fn->call_list.at(i);
6741 if (call->new_stack != nullptr) {
6742 // don't need to allocate a frame for this
6743 continue;
6744 }
6745 ZigFn *callee = call->fn_entry;
6746 if (callee == nullptr) {
6747 if (call->fn_ref->value->type->data.fn.fn_type_id.cc != CallingConventionAsync) {
6748 continue;
6749 }
6750 add_node_error(g, call->base.source_node,
6751 buf_sprintf("function is not comptime-known; @asyncCall required"));
6752 return ErrorSemanticAnalyzeFail;
6753 }
6754 if (callee->body_node == nullptr) {
6755 continue;
6756 }
6757 if (callee->anal_state == FnAnalStateProbing) {
6758 ErrorMsg *msg = add_node_error(g, fn->proto_node,
6759 buf_sprintf("unable to determine async function frame of '%s'", buf_ptr(&fn->symbol_name)));
6760 g->trace_err = add_error_note(g, msg, call->base.source_node,
6761 buf_sprintf("analysis of function '%s' depends on the frame", buf_ptr(&callee->symbol_name)));
6762 return ErrorSemanticAnalyzeFail;
6763 }
6764
6765 ZigType *callee_frame_type = get_fn_frame_type(g, callee);
6766 frame_type->data.frame.resolve_loop_type = callee_frame_type;
6767 frame_type->data.frame.resolve_loop_src_node = call->base.source_node;
6768
6769 analyze_fn_body(g, callee);
6770 if (callee->anal_state == FnAnalStateInvalid) {
6771 frame_type->data.frame.locals_struct = g->builtin_types.entry_invalid;
6772 return ErrorSemanticAnalyzeFail;
6773 }
6774 analyze_fn_async(g, callee, true);
6775 if (callee->inferred_async_node == inferred_async_checking) {
6776 assert(g->errors.length != 0);
6777 frame_type->data.frame.locals_struct = g->builtin_types.entry_invalid;
6778 return ErrorSemanticAnalyzeFail;
6779 }
6780 if (!fn_is_async(callee))
6781 continue;
6782
6783 mark_suspension_point(call->base.scope);
6784
6785 if ((err = type_resolve(g, callee_frame_type, ResolveStatusSizeKnown))) {
6786 return err;
6787 }
6788 if (largest_call_frame_type == nullptr ||
6789 callee_frame_type->abi_size > largest_call_frame_type->abi_size)
6790 {
6791 largest_call_frame_type = callee_frame_type;
6792 }
6793
6794 call->frame_result_loc = all_calls_alloca;
6795 }
6796 if (largest_call_frame_type != nullptr) {
6797 all_calls_alloca->value->type = get_pointer_to_type(g, largest_call_frame_type, false);
6798 }
6799
6800 // Since this frame is async, an await might represent a suspend point, and
6801 // therefore need to spill. It also needs to mark expr scopes as having to spill.
6802 // For example: foo() + await z
6803 // The function call result of foo() must be spilled.
6804 for (size_t i = 0; i < fn->await_list.length; i += 1) {
6805 Stage1AirInstAwait *await = fn->await_list.at(i);
6806 if (await->is_nosuspend) {
6807 continue;
6808 }
6809 if (await->base.value->special != ConstValSpecialRuntime) {
6810 // Known at comptime. No spill, no suspend.
6811 continue;
6812 }
6813 if (await->target_fn != nullptr) {
6814 // we might not need to suspend
6815 analyze_fn_async(g, await->target_fn, false);
6816 if (await->target_fn->anal_state == FnAnalStateInvalid) {
6817 frame_type->data.frame.locals_struct = g->builtin_types.entry_invalid;
6818 return ErrorSemanticAnalyzeFail;
6819 }
6820 if (!fn_is_async(await->target_fn)) {
6821 // This await does not represent a suspend point. No spill needed,
6822 // and no need to mark ExprScope.
6823 continue;
6824 }
6825 }
6826 // This await is a suspend point, but it might not need a spill.
6827 // We do need to mark the ExprScope as having a suspend point in it.
6828 mark_suspension_point(await->base.scope);
6829
6830 if (await->result_loc != nullptr) {
6831 // If there's a result location, that is the spill
6832 continue;
6833 }
6834 if (await->base.ref_count == 0)
6835 continue;
6836 if (!type_has_bits(g, await->base.value->type))
6837 continue;
6838 await->result_loc = ir_create_alloca(g, await->base.scope, await->base.source_node, fn,
6839 await->base.value->type, "");
6840 }
6841 for (size_t block_i = 0; block_i < fn->analyzed_executable.basic_block_list.length; block_i += 1) {
6842 Stage1AirBasicBlock *block = fn->analyzed_executable.basic_block_list.at(block_i);
6843 for (size_t instr_i = 0; instr_i < block->instruction_list.length; instr_i += 1) {
6844 Stage1AirInst *instruction = block->instruction_list.at(instr_i);
6845 if (instruction->id == Stage1AirInstIdSuspendFinish) {
6846 mark_suspension_point(instruction->scope);
6847 }
6848 }
6849 }
6850 // Now that we've marked all the expr scopes that have to spill, we go over the instructions
6851 // and spill the relevant ones.
6852 for (size_t block_i = 0; block_i < fn->analyzed_executable.basic_block_list.length; block_i += 1) {
6853 Stage1AirBasicBlock *block = fn->analyzed_executable.basic_block_list.at(block_i);
6854 for (size_t instr_i = 0; instr_i < block->instruction_list.length; instr_i += 1) {
6855 Stage1AirInst *instruction = block->instruction_list.at(instr_i);
6856 if (instruction->id == Stage1AirInstIdAwait ||
6857 instruction->id == Stage1AirInstIdVarPtr ||
6858 instruction->id == Stage1AirInstIdAlloca ||
6859 instruction->id == Stage1AirInstIdSpillBegin ||
6860 instruction->id == Stage1AirInstIdSpillEnd)
6861 {
6862 // This instruction does its own spilling specially, or otherwise doesn't need it.
6863 continue;
6864 }
6865 if (instruction->id == Stage1AirInstIdCast &&
6866 reinterpret_cast<Stage1AirInstCast *>(instruction)->cast_op == CastOpNoop)
6867 {
6868 // The IR instruction exists only to change the type according to Zig. No spill needed.
6869 continue;
6870 }
6871 if (instruction->value->special != ConstValSpecialRuntime)
6872 continue;
6873 if (instruction->ref_count == 0)
6874 continue;
6875 if ((err = type_resolve(g, instruction->value->type, ResolveStatusZeroBitsKnown)))
6876 return ErrorSemanticAnalyzeFail;
6877 if (!type_has_bits(g, instruction->value->type))
6878 continue;
6879 if (scope_needs_spill(instruction->scope)) {
6880 instruction->spill = ir_create_alloca(g, instruction->scope, instruction->source_node,
6881 fn, instruction->value->type, "");
6882 }
6883 }
6884 }
6885
6886 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
6887 ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false);
6888
6889 // label (grep this): [fn_frame_struct_layout]
6890 ZigList<SrcField> fields = {};
6891
6892 fields.append({"@fn_ptr", fn_type, 0});
6893 fields.append({"@resume_index", g->builtin_types.entry_usize, 0});
6894 fields.append({"@awaiter", g->builtin_types.entry_usize, 0});
6895
6896 fields.append({"@result_ptr_callee", ptr_return_type, 0});
6897 fields.append({"@result_ptr_awaiter", ptr_return_type, 0});
6898 fields.append({"@result", fn_type_id->return_type, 0});
6899
6900 if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) {
6901 ZigType *ptr_stack_trace_type = get_pointer_to_type(g, get_stack_trace_type(g), false);
6902 fields.append({"@ptr_stack_trace_callee", ptr_stack_trace_type, 0});
6903 fields.append({"@ptr_stack_trace_awaiter", ptr_stack_trace_type, 0});
6904 }
6905
6906 for (size_t arg_i = 0; arg_i < fn_type_id->param_count; arg_i += 1) {
6907 FnTypeParamInfo *param_info = &fn_type_id->param_info[arg_i];
6908 AstNode *param_decl_node = get_param_decl_node(fn, arg_i);
6909 Buf *param_name;
6910 bool is_var_args = param_decl_node && param_decl_node->data.param_decl.is_var_args;
6911 if (param_decl_node && !is_var_args) {
6912 param_name = param_decl_node->data.param_decl.name;
6913 } else {
6914 param_name = buf_sprintf("@arg%" ZIG_PRI_usize, arg_i);
6915 }
6916 ZigType *param_type = resolve_type_isf(param_info->type);
6917 if ((err = type_resolve(g, param_type, ResolveStatusSizeKnown))) {
6918 return err;
6919 }
6920
6921 fields.append({buf_ptr(param_name), param_type, 0});
6922 }
6923
6924 if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) {
6925 fields.append({"@stack_trace", get_stack_trace_type(g), 0});
6926 fields.append({"@instruction_addresses",
6927 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, nullptr), 0});
6928 }
6929
6930 for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {
6931 Stage1AirInstAlloca *instruction = fn->alloca_gen_list.at(alloca_i);
6932 instruction->field_index = SIZE_MAX;
6933 ZigType *ptr_type = instruction->base.value->type;
6934 assert(ptr_type->id == ZigTypeIdPointer);
6935 ZigType *child_type = resolve_type_isf(ptr_type->data.pointer.child_type);
6936 if (!type_has_bits(g, child_type))
6937 continue;
6938 if (instruction->base.ref_count == 0)
6939 continue;
6940 if (instruction->base.value->special != ConstValSpecialRuntime) {
6941 if (const_ptr_pointee(nullptr, g, instruction->base.value, nullptr)->special !=
6942 ConstValSpecialRuntime)
6943 {
6944 continue;
6945 }
6946 }
6947
6948 frame_type->data.frame.resolve_loop_type = child_type;
6949 frame_type->data.frame.resolve_loop_src_node = instruction->base.source_node;
6950 if ((err = type_resolve(g, child_type, ResolveStatusSizeKnown))) {
6951 return err;
6952 }
6953
6954 const char *name;
6955 if (*instruction->name_hint == 0) {
6956 name = buf_ptr(buf_sprintf("@local%" ZIG_PRI_usize, alloca_i));
6957 } else {
6958 name = buf_ptr(buf_sprintf("%s.%" ZIG_PRI_usize, instruction->name_hint, alloca_i));
6959 }
6960 instruction->field_index = fields.length;
6961
6962 fields.append({name, child_type, instruction->align});
6963 }
6964
6965
6966 frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),
6967 fields.items, fields.length, target_fn_align(g->zig_target));
6968 frame_type->abi_size = frame_type->data.frame.locals_struct->abi_size;
6969 frame_type->abi_align = frame_type->data.frame.locals_struct->abi_align;
6970 frame_type->size_in_bits = frame_type->data.frame.locals_struct->size_in_bits;
6971
6972 if (g->largest_frame_fn == nullptr || frame_type->abi_size > g->largest_frame_fn->frame_type->abi_size) {
6973 g->largest_frame_fn = fn;
6974 }
6975
6976 return ErrorNone;
6977}
6978
6979static Error resolve_pointer_zero_bits(CodeGen *g, ZigType *ty) {
6980 Error err;
6981
6982 if (ty->abi_size != SIZE_MAX)
6983 return ErrorNone;
6984
6985 if (ty->data.pointer.resolve_loop_flag_zero_bits) {
6986 ty->abi_size = g->builtin_types.entry_usize->abi_size;
6987 ty->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
6988 ty->abi_align = g->builtin_types.entry_usize->abi_align;
6989 return ErrorNone;
6990 }
6991 ty->data.pointer.resolve_loop_flag_zero_bits = true;
6992
6993 ZigType *elem_type;
6994 InferredStructField *isf = ty->data.pointer.inferred_struct_field;
6995 if (isf != nullptr) {
6996 TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
6997 assert(field != nullptr);
6998 if (field->is_comptime) {
6999 ty->data.pointer.resolve_loop_flag_zero_bits = false;
7000
7001 ty->abi_size = 0;
7002 ty->size_in_bits = 0;
7003 ty->abi_align = 0;
7004
7005 return ErrorNone;
7006 }
7007 elem_type = field->type_entry;
7008 } else {
7009 elem_type = ty->data.pointer.child_type;
7010 }
7011
7012 bool has_bits;
7013 if ((err = type_has_bits2(g, elem_type, &has_bits)))
7014 return err;
7015
7016 ty->data.pointer.resolve_loop_flag_zero_bits = false;
7017
7018 if (has_bits) {
7019 ty->abi_size = g->builtin_types.entry_usize->abi_size;
7020 ty->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
7021 ty->abi_align = g->builtin_types.entry_usize->abi_align;
7022 } else {
7023 ty->abi_size = 0;
7024 ty->size_in_bits = 0;
7025 ty->abi_align = 0;
7026 }
7027 return ErrorNone;
7028}
7029
7030Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
7031 if (type_is_invalid(ty))
7032 return ErrorSemanticAnalyzeFail;
7033 switch (status) {
7034 case ResolveStatusUnstarted:
7035 return ErrorNone;
7036 case ResolveStatusBeingInferred:
7037 zig_unreachable();
7038 case ResolveStatusInvalid:
7039 zig_unreachable();
7040 case ResolveStatusZeroBitsKnown:
7041 switch (ty->id) {
7042 case ZigTypeIdStruct:
7043 return resolve_struct_zero_bits(g, ty);
7044 case ZigTypeIdEnum:
7045 return resolve_enum_zero_bits(g, ty);
7046 case ZigTypeIdUnion:
7047 return resolve_union_zero_bits(g, ty);
7048 case ZigTypeIdPointer:
7049 return resolve_pointer_zero_bits(g, ty);
7050 default:
7051 return ErrorNone;
7052 }
7053 case ResolveStatusAlignmentKnown:
7054 switch (ty->id) {
7055 case ZigTypeIdStruct:
7056 return resolve_struct_alignment(g, ty);
7057 case ZigTypeIdEnum:
7058 return resolve_enum_zero_bits(g, ty);
7059 case ZigTypeIdUnion:
7060 return resolve_union_alignment(g, ty);
7061 case ZigTypeIdFnFrame:
7062 return resolve_async_frame(g, ty);
7063 case ZigTypeIdPointer:
7064 return resolve_pointer_zero_bits(g, ty);
7065 default:
7066 return ErrorNone;
7067 }
7068 case ResolveStatusSizeKnown:
7069 switch (ty->id) {
7070 case ZigTypeIdStruct:
7071 return resolve_struct_type(g, ty);
7072 case ZigTypeIdEnum:
7073 return resolve_enum_zero_bits(g, ty);
7074 case ZigTypeIdUnion:
7075 return resolve_union_type(g, ty);
7076 case ZigTypeIdFnFrame:
7077 return resolve_async_frame(g, ty);
7078 case ZigTypeIdPointer:
7079 return resolve_pointer_zero_bits(g, ty);
7080 default:
7081 return ErrorNone;
7082 }
7083 case ResolveStatusLLVMFwdDecl:
7084 case ResolveStatusLLVMFull:
7085 resolve_llvm_types(g, ty, status);
7086 return ErrorNone;
7087 }
7088 zig_unreachable();
7089}
7090
7091bool ir_get_var_is_comptime(ZigVar *var) {
7092 if (var->is_comptime_memoized)
7093 return var->is_comptime_memoized_value;
7094
7095 var->is_comptime_memoized = true;
7096
7097 // The is_comptime field can be left null, which means not comptime.
7098 if (var->is_comptime == nullptr) {
7099 var->is_comptime_memoized_value = false;
7100 return var->is_comptime_memoized_value;
7101 }
7102 // When the is_comptime field references an instruction that has to get analyzed, this
7103 // is the value.
7104 if (var->is_comptime->child != nullptr) {
7105 assert(var->is_comptime->child->value->type->id == ZigTypeIdBool);
7106 var->is_comptime_memoized_value = var->is_comptime->child->value->data.x_bool;
7107 var->is_comptime = nullptr;
7108 return var->is_comptime_memoized_value;
7109 }
7110 // As an optimization, is_comptime values which are constant are allowed
7111 // to be omitted from analysis. In this case, there is no child instruction
7112 // and we simply look at the unanalyzed const parent instruction.
7113 assert(var->is_comptime->id == Stage1ZirInstIdConst);
7114 Stage1ZirInstConst *const_inst = reinterpret_cast<Stage1ZirInstConst *>(var->is_comptime);
7115 assert(const_inst->value->type->id == ZigTypeIdBool);
7116 var->is_comptime_memoized_value = const_inst->value->data.x_bool;
7117 var->is_comptime = nullptr;
7118 return var->is_comptime_memoized_value;
7119}
7120
7121bool const_values_equal_ptr(ZigValue *a, ZigValue *b) {
7122 if (a->data.x_ptr.special != b->data.x_ptr.special)
7123 return false;
7124 switch (a->data.x_ptr.special) {
7125 case ConstPtrSpecialInvalid:
7126 zig_unreachable();
7127 case ConstPtrSpecialRef:
7128 if (a->data.x_ptr.data.ref.pointee != b->data.x_ptr.data.ref.pointee)
7129 return false;
7130 return true;
7131 case ConstPtrSpecialBaseArray:
7132 case ConstPtrSpecialSubArray:
7133 if (a->data.x_ptr.data.base_array.array_val != b->data.x_ptr.data.base_array.array_val) {
7134 return false;
7135 }
7136 if (a->data.x_ptr.data.base_array.elem_index != b->data.x_ptr.data.base_array.elem_index)
7137 return false;
7138 return true;
7139 case ConstPtrSpecialBaseStruct:
7140 if (a->data.x_ptr.data.base_struct.struct_val != b->data.x_ptr.data.base_struct.struct_val) {
7141 return false;
7142 }
7143 if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)
7144 return false;
7145 return true;
7146 case ConstPtrSpecialBaseErrorUnionCode:
7147 if (a->data.x_ptr.data.base_err_union_code.err_union_val !=
7148 b->data.x_ptr.data.base_err_union_code.err_union_val)
7149 {
7150 return false;
7151 }
7152 return true;
7153 case ConstPtrSpecialBaseErrorUnionPayload:
7154 if (a->data.x_ptr.data.base_err_union_payload.err_union_val !=
7155 b->data.x_ptr.data.base_err_union_payload.err_union_val)
7156 {
7157 return false;
7158 }
7159 return true;
7160 case ConstPtrSpecialBaseOptionalPayload:
7161 if (a->data.x_ptr.data.base_optional_payload.optional_val !=
7162 b->data.x_ptr.data.base_optional_payload.optional_val)
7163 {
7164 return false;
7165 }
7166 return true;
7167 case ConstPtrSpecialHardCodedAddr:
7168 if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)
7169 return false;
7170 return true;
7171 case ConstPtrSpecialDiscard:
7172 return true;
7173 case ConstPtrSpecialFunction:
7174 return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;
7175 case ConstPtrSpecialNull:
7176 return true;
7177 }
7178 zig_unreachable();
7179}
7180
7181static bool const_values_equal_array(CodeGen *g, ZigValue *a, ZigValue *b, size_t len) {
7182 if (a->data.x_array.special == ConstArraySpecialUndef &&
7183 b->data.x_array.special == ConstArraySpecialUndef)
7184 {
7185 return true;
7186 }
7187 if (a->data.x_array.special == ConstArraySpecialUndef ||
7188 b->data.x_array.special == ConstArraySpecialUndef)
7189 {
7190 return false;
7191 }
7192 if (a->data.x_array.special == ConstArraySpecialBuf &&
7193 b->data.x_array.special == ConstArraySpecialBuf)
7194 {
7195 return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf);
7196 }
7197 expand_undef_array(g, a);
7198 expand_undef_array(g, b);
7199
7200 ZigValue *a_elems = a->data.x_array.data.s_none.elements;
7201 ZigValue *b_elems = b->data.x_array.data.s_none.elements;
7202
7203 for (size_t i = 0; i < len; i += 1) {
7204 if (!const_values_equal(g, &a_elems[i], &b_elems[i]))
7205 return false;
7206 }
7207
7208 return true;
7209}
7210
7211bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) {
7212 if (a->type->id != b->type->id) return false;
7213 if (a->type == b->type) {
7214 switch (type_has_one_possible_value(g, a->type)) {
7215 case OnePossibleValueInvalid:
7216 zig_unreachable();
7217 case OnePossibleValueNo:
7218 break;
7219 case OnePossibleValueYes:
7220 return true;
7221 }
7222 }
7223 if (a->special == ConstValSpecialUndef || b->special == ConstValSpecialUndef) {
7224 return a->special == b->special;
7225 }
7226 assert(a->special == ConstValSpecialStatic);
7227 assert(b->special == ConstValSpecialStatic);
7228 switch (a->type->id) {
7229 case ZigTypeIdOpaque:
7230 zig_unreachable();
7231 case ZigTypeIdEnum:
7232 return bigint_cmp(&a->data.x_enum_tag, &b->data.x_enum_tag) == CmpEQ;
7233 case ZigTypeIdUnion: {
7234 ConstUnionValue *union1 = &a->data.x_union;
7235 ConstUnionValue *union2 = &b->data.x_union;
7236
7237 if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) {
7238 TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag);
7239 assert(field != nullptr);
7240 assert(find_union_field_by_tag(a->type, &union2->tag) != nullptr);
7241 return const_values_equal(g, union1->payload, union2->payload);
7242 }
7243 return false;
7244 }
7245 case ZigTypeIdMetaType:
7246 return a->data.x_type == b->data.x_type;
7247 case ZigTypeIdVoid:
7248 case ZigTypeIdUndefined:
7249 case ZigTypeIdNull:
7250 return true;
7251 case ZigTypeIdErrorSet:
7252 return a->data.x_err_set->value == b->data.x_err_set->value;
7253 case ZigTypeIdBool:
7254 return a->data.x_bool == b->data.x_bool;
7255 case ZigTypeIdFloat:
7256 assert(a->type->data.floating.bit_count == b->type->data.floating.bit_count);
7257 switch (a->type->data.floating.bit_count) {
7258 case 16:
7259 return f16_eq(a->data.x_f16, b->data.x_f16);
7260 case 32:
7261 return a->data.x_f32 == b->data.x_f32;
7262 case 64:
7263 return a->data.x_f64 == b->data.x_f64;
7264 case 80:
7265 return extF80M_eq(&a->data.x_f80, &b->data.x_f80);
7266 case 128:
7267 return f128M_eq(&a->data.x_f128, &b->data.x_f128);
7268 default:
7269 zig_unreachable();
7270 }
7271 case ZigTypeIdComptimeFloat:
7272 return bigfloat_cmp(&a->data.x_bigfloat, &b->data.x_bigfloat) == CmpEQ;
7273 case ZigTypeIdInt:
7274 case ZigTypeIdComptimeInt:
7275 return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ;
7276 case ZigTypeIdEnumLiteral:
7277 return buf_eql_buf(a->data.x_enum_literal, b->data.x_enum_literal);
7278 case ZigTypeIdPointer:
7279 case ZigTypeIdFn:
7280 return const_values_equal_ptr(a, b);
7281 case ZigTypeIdVector:
7282 assert(a->type->data.vector.len == b->type->data.vector.len);
7283 return const_values_equal_array(g, a, b, a->type->data.vector.len);
7284 case ZigTypeIdArray:
7285 assert(a->type->data.array.len == b->type->data.array.len);
7286 return const_values_equal_array(g, a, b, a->type->data.array.len);
7287 case ZigTypeIdStruct:
7288 for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) {
7289 if (a->type->data.structure.fields[i]->is_comptime) {
7290 // The values of comptime struct fields are part of the
7291 // type, not the value, so they do not participate in equality
7292 // or hash of comptime values.
7293 continue;
7294 }
7295 ZigValue *field_a = a->data.x_struct.fields[i];
7296 ZigValue *field_b = b->data.x_struct.fields[i];
7297 if (!const_values_equal(g, field_a, field_b))
7298 return false;
7299 }
7300 return true;
7301 case ZigTypeIdFnFrame:
7302 zig_panic("TODO: const_values_equal ZigTypeIdFnFrame");
7303 case ZigTypeIdAnyFrame:
7304 zig_panic("TODO: const_values_equal ZigTypeIdAnyFrame");
7305 case ZigTypeIdOptional:
7306 if (get_src_ptr_type(a->type) != nullptr)
7307 return const_values_equal_ptr(a, b);
7308 if (a->data.x_optional == nullptr || b->data.x_optional == nullptr) {
7309 return (a->data.x_optional == nullptr && b->data.x_optional == nullptr);
7310 } else {
7311 return const_values_equal(g, a->data.x_optional, b->data.x_optional);
7312 }
7313 case ZigTypeIdErrorUnion: {
7314 bool a_is_err = a->data.x_err_union.error_set->data.x_err_set != nullptr;
7315 bool b_is_err = b->data.x_err_union.error_set->data.x_err_set != nullptr;
7316 if (a_is_err != b_is_err) return false;
7317 if (a_is_err) {
7318 return const_values_equal(g, a->data.x_err_union.error_set, b->data.x_err_union.error_set);
7319 } else {
7320 return const_values_equal(g, a->data.x_err_union.payload, b->data.x_err_union.payload);
7321 }
7322 }
7323 case ZigTypeIdBoundFn:
7324 case ZigTypeIdInvalid:
7325 case ZigTypeIdUnreachable:
7326 zig_unreachable();
7327 }
7328 zig_unreachable();
7329}
7330
7331void eval_min_max_value_int(CodeGen *g, ZigType *int_type, BigInt *bigint, bool is_max) {
7332 assert(int_type->id == ZigTypeIdInt);
7333 if (int_type->data.integral.bit_count == 0) {
7334 bigint_init_unsigned(bigint, 0);
7335 return;
7336 }
7337 if (is_max) {
7338 // is_signed=true (1 << (bit_count - 1)) - 1
7339 // is_signed=false (1 << (bit_count - 0)) - 1
7340 BigInt one = {0};
7341 bigint_init_unsigned(&one, 1);
7342
7343 size_t shift_amt = int_type->data.integral.bit_count - (int_type->data.integral.is_signed ? 1 : 0);
7344 BigInt bit_count_bi = {0};
7345 bigint_init_unsigned(&bit_count_bi, shift_amt);
7346
7347 BigInt shifted_bi = {0};
7348 bigint_shl(&shifted_bi, &one, &bit_count_bi);
7349
7350 bigint_sub(bigint, &shifted_bi, &one);
7351 } else if (int_type->data.integral.is_signed) {
7352 // - (1 << (bit_count - 1))
7353 BigInt one = {0};
7354 bigint_init_unsigned(&one, 1);
7355
7356 BigInt bit_count_bi = {0};
7357 bigint_init_unsigned(&bit_count_bi, int_type->data.integral.bit_count - 1);
7358
7359 BigInt shifted_bi = {0};
7360 bigint_shl(&shifted_bi, &one, &bit_count_bi);
7361
7362 bigint_negate(bigint, &shifted_bi);
7363 } else {
7364 bigint_init_unsigned(bigint, 0);
7365 }
7366}
7367
7368void eval_min_max_value(CodeGen *g, ZigType *type_entry, ZigValue *const_val, bool is_max) {
7369 if (type_entry->id == ZigTypeIdInt) {
7370 const_val->special = ConstValSpecialStatic;
7371 eval_min_max_value_int(g, type_entry, &const_val->data.x_bigint, is_max);
7372 } else if (type_entry->id == ZigTypeIdBool) {
7373 const_val->special = ConstValSpecialStatic;
7374 const_val->data.x_bool = is_max;
7375 } else if (type_entry->id == ZigTypeIdVoid) {
7376 // nothing to do
7377 } else {
7378 zig_unreachable();
7379 }
7380}
7381
7382static void render_const_val_ptr(CodeGen *g, Buf *buf, ZigValue *const_val, ZigType *type_entry) {
7383 if (type_entry->id == ZigTypeIdPointer && type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {
7384 buf_append_buf(buf, &type_entry->name);
7385 return;
7386 }
7387
7388 switch (const_val->data.x_ptr.special) {
7389 case ConstPtrSpecialInvalid:
7390 zig_unreachable();
7391 case ConstPtrSpecialRef:
7392 case ConstPtrSpecialBaseStruct:
7393 case ConstPtrSpecialBaseErrorUnionCode:
7394 case ConstPtrSpecialBaseErrorUnionPayload:
7395 case ConstPtrSpecialBaseOptionalPayload:
7396 buf_appendf(buf, "*");
7397 // TODO we need a source node for const_ptr_pointee because it can generate compile errors
7398 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
7399 return;
7400 case ConstPtrSpecialBaseArray:
7401 case ConstPtrSpecialSubArray:
7402 buf_appendf(buf, "*");
7403 // TODO we need a source node for const_ptr_pointee because it can generate compile errors
7404 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
7405 return;
7406 case ConstPtrSpecialHardCodedAddr:
7407 buf_appendf(buf, "(%s)(%" ZIG_PRI_x64 ")", buf_ptr(&type_entry->name),
7408 const_val->data.x_ptr.data.hard_coded_addr.addr);
7409 return;
7410 case ConstPtrSpecialDiscard:
7411 buf_append_str(buf, "*_");
7412 return;
7413 case ConstPtrSpecialFunction:
7414 {
7415 ZigFn *fn_entry = const_val->data.x_ptr.data.fn.fn_entry;
7416 buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name));
7417 return;
7418 }
7419 case ConstPtrSpecialNull:
7420 buf_append_str(buf, "null");
7421 return;
7422 }
7423 zig_unreachable();
7424}
7425
7426static void render_const_val_err_set(CodeGen *g, Buf *buf, ZigValue *const_val, ZigType *type_entry) {
7427 if (const_val->data.x_err_set == nullptr) {
7428 buf_append_str(buf, "null");
7429 } else {
7430 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
7431 }
7432}
7433
7434static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ZigValue *const_val, uint64_t start, uint64_t len) {
7435 ConstArrayValue *array = &const_val->data.x_array;
7436 switch (array->special) {
7437 case ConstArraySpecialUndef:
7438 buf_append_str(buf, "undefined");
7439 return;
7440 case ConstArraySpecialBuf: {
7441 Buf *array_buf = array->data.s_buf;
7442 const char *base = &buf_ptr(array_buf)[start];
7443 assert(start + len <= buf_len(array_buf));
7444
7445 buf_append_char(buf, '"');
7446 for (size_t i = 0; i < len; i += 1) {
7447 uint8_t c = base[i];
7448 if (c == '"') {
7449 buf_append_str(buf, "\\\"");
7450 } else {
7451 buf_append_char(buf, c);
7452 }
7453 }
7454 buf_append_char(buf, '"');
7455 return;
7456 }
7457 case ConstArraySpecialNone: {
7458 assert(start + len <= const_val->type->data.array.len);
7459 ZigValue *base = &array->data.s_none.elements[start];
7460 assert(len == 0 || base != nullptr);
7461
7462 buf_appendf(buf, "%s{", buf_ptr(type_name));
7463 for (uint64_t i = 0; i < len; i += 1) {
7464 if (i != 0) buf_appendf(buf, ",");
7465 render_const_value(g, buf, &base[i]);
7466 }
7467 buf_appendf(buf, "}");
7468 return;
7469 }
7470 }
7471 zig_unreachable();
7472}
7473
7474void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) {
7475 if (const_val == nullptr) {
7476 buf_appendf(buf, "(invalid nullptr value)");
7477 return;
7478 }
7479 switch (const_val->special) {
7480 case ConstValSpecialRuntime:
7481 buf_appendf(buf, "(runtime value)");
7482 return;
7483 case ConstValSpecialLazy:
7484 buf_appendf(buf, "(lazy value)");
7485 return;
7486 case ConstValSpecialUndef:
7487 buf_appendf(buf, "undefined");
7488 return;
7489 case ConstValSpecialStatic:
7490 break;
7491 }
7492 assert(const_val->type);
7493
7494 ZigType *type_entry = const_val->type;
7495 switch (type_entry->id) {
7496 case ZigTypeIdOpaque:
7497 zig_unreachable();
7498 case ZigTypeIdInvalid:
7499 buf_appendf(buf, "(invalid)");
7500 return;
7501 case ZigTypeIdVoid:
7502 buf_appendf(buf, "{}");
7503 return;
7504 case ZigTypeIdComptimeFloat:
7505 bigfloat_append_buf(buf, &const_val->data.x_bigfloat);
7506 return;
7507 case ZigTypeIdFloat:
7508 switch (type_entry->data.floating.bit_count) {
7509 case 16:
7510 buf_appendf(buf, "%f", zig_f16_to_double(const_val->data.x_f16));
7511 return;
7512 case 32:
7513 buf_appendf(buf, "%f", const_val->data.x_f32);
7514 return;
7515 case 64:
7516 buf_appendf(buf, "%f", const_val->data.x_f64);
7517 return;
7518 case 80: {
7519 float64_t f64_value = extF80M_to_f64(&const_val->data.x_f80);
7520 double double_value;
7521 memcpy(&double_value, &f64_value, sizeof(double));
7522 buf_appendf(buf, "%f", double_value);
7523 return;
7524 }
7525 case 128:
7526 {
7527 const size_t extra_len = 100;
7528 size_t old_len = buf_len(buf);
7529 buf_resize(buf, old_len + extra_len);
7530 float64_t f64_value = f128M_to_f64(&const_val->data.x_f128);
7531 double double_value;
7532 memcpy(&double_value, &f64_value, sizeof(double));
7533 // TODO actual f128 printing to decimal
7534 int len = snprintf(buf_ptr(buf) + old_len, extra_len, "%f", double_value);
7535 assert(len > 0);
7536 buf_resize(buf, old_len + len);
7537 return;
7538 }
7539 default:
7540 zig_unreachable();
7541 }
7542 case ZigTypeIdComptimeInt:
7543 case ZigTypeIdInt:
7544 bigint_append_buf(buf, &const_val->data.x_bigint, 10);
7545 return;
7546 case ZigTypeIdEnumLiteral:
7547 buf_append_buf(buf, const_val->data.x_enum_literal);
7548 return;
7549 case ZigTypeIdMetaType:
7550 buf_appendf(buf, "%s", buf_ptr(&const_val->data.x_type->name));
7551 return;
7552 case ZigTypeIdUnreachable:
7553 buf_appendf(buf, "unreachable");
7554 return;
7555 case ZigTypeIdBool:
7556 {
7557 const char *value = const_val->data.x_bool ? "true" : "false";
7558 buf_appendf(buf, "%s", value);
7559 return;
7560 }
7561 case ZigTypeIdFn:
7562 {
7563 assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
7564 assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction);
7565 ZigFn *fn_entry = const_val->data.x_ptr.data.fn.fn_entry;
7566 buf_appendf(buf, "%s", buf_ptr(&fn_entry->symbol_name));
7567 return;
7568 }
7569 case ZigTypeIdPointer:
7570 return render_const_val_ptr(g, buf, const_val, type_entry);
7571 case ZigTypeIdArray: {
7572 uint64_t len = type_entry->data.array.len;
7573 render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
7574 return;
7575 }
7576 case ZigTypeIdVector: {
7577 uint32_t len = type_entry->data.vector.len;
7578 render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
7579 return;
7580 }
7581 case ZigTypeIdNull:
7582 {
7583 buf_appendf(buf, "null");
7584 return;
7585 }
7586 case ZigTypeIdUndefined:
7587 {
7588 buf_appendf(buf, "undefined");
7589 return;
7590 }
7591 case ZigTypeIdOptional:
7592 {
7593 ZigType *src_ptr_type = get_src_ptr_type(const_val->type);
7594 if (src_ptr_type != nullptr) {
7595 if (src_ptr_type->id == ZigTypeIdPointer && !optional_value_is_null(const_val)) {
7596 ZigValue tmp = {};
7597 copy_const_val(g, &tmp, const_val);
7598 tmp.type = type_entry->data.maybe.child_type;
7599 return render_const_val_ptr(g, buf, &tmp, tmp.type);
7600 }
7601 return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type);
7602 }
7603 if (type_entry->data.maybe.child_type->id == ZigTypeIdErrorSet)
7604 return render_const_val_err_set(g, buf, const_val, type_entry->data.maybe.child_type);
7605 if (const_val->data.x_optional) {
7606 render_const_value(g, buf, const_val->data.x_optional);
7607 } else {
7608 buf_appendf(buf, "null");
7609 }
7610 return;
7611 }
7612 case ZigTypeIdBoundFn:
7613 {
7614 ZigFn *fn_entry = const_val->data.x_bound_fn.fn;
7615 buf_appendf(buf, "(bound fn %s)", buf_ptr(&fn_entry->symbol_name));
7616 return;
7617 }
7618 case ZigTypeIdStruct:
7619 {
7620 if (is_slice(type_entry)) {
7621 ZigValue *len_val = const_val->data.x_struct.fields[slice_len_index];
7622 size_t len = bigint_as_usize(&len_val->data.x_bigint);
7623
7624 ZigValue *ptr_val = const_val->data.x_struct.fields[slice_ptr_index];
7625 if (ptr_val->special == ConstValSpecialUndef) {
7626 assert(len == 0);
7627 buf_appendf(buf, "((%s)(undefined))[0..0]", buf_ptr(&type_entry->name));
7628 return;
7629 }
7630 assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
7631 ZigValue *array = ptr_val->data.x_ptr.data.base_array.array_val;
7632 size_t start = ptr_val->data.x_ptr.data.base_array.elem_index;
7633
7634 if (array->special == ConstValSpecialUndef)
7635 buf_append_str(buf, "undefined");
7636 else
7637 render_const_val_array(g, buf, &type_entry->name, array, start, len);
7638 } else {
7639 buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name));
7640 }
7641 return;
7642 }
7643 case ZigTypeIdEnum:
7644 {
7645 TypeEnumField *field = find_enum_field_by_tag(type_entry, &const_val->data.x_enum_tag);
7646 if(field != nullptr){
7647 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(field->name));
7648 } else {
7649 // untagged value in a non-exhaustive enum
7650 buf_appendf(buf, "%s.(", buf_ptr(&type_entry->name));
7651 bigint_append_buf(buf, &const_val->data.x_enum_tag, 10);
7652 buf_appendf(buf, ")");
7653 }
7654 return;
7655 }
7656 case ZigTypeIdErrorUnion:
7657 {
7658 buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));
7659 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
7660 if (err_set == nullptr) {
7661 render_const_value(g, buf, const_val->data.x_err_union.payload);
7662 } else {
7663 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),
7664 buf_ptr(&err_set->name));
7665 }
7666 buf_appendf(buf, ")");
7667 return;
7668 }
7669 case ZigTypeIdUnion:
7670 {
7671 const BigInt *tag = &const_val->data.x_union.tag;
7672 TypeUnionField *field = find_union_field_by_tag(type_entry, tag);
7673 buf_appendf(buf, "%s { .%s = ", buf_ptr(&type_entry->name), buf_ptr(field->name));
7674 render_const_value(g, buf, const_val->data.x_union.payload);
7675 buf_append_str(buf, "}");
7676 return;
7677 }
7678 case ZigTypeIdErrorSet:
7679 return render_const_val_err_set(g, buf, const_val, type_entry);
7680 case ZigTypeIdFnFrame:
7681 buf_appendf(buf, "(TODO: async function frame value)");
7682 return;
7683
7684 case ZigTypeIdAnyFrame:
7685 buf_appendf(buf, "(TODO: anyframe value)");
7686 return;
7687
7688 }
7689 zig_unreachable();
7690}
7691
7692ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
7693 assert(size_in_bits <= 65535);
7694 ZigType *entry = new_type_table_entry(ZigTypeIdInt);
7695
7696 entry->size_in_bits = size_in_bits;
7697 if (size_in_bits != 0) {
7698 entry->llvm_type = LLVMIntType(size_in_bits);
7699 entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type);
7700 entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type);
7701
7702 if (size_in_bits >= 128 && entry->abi_align < 16) {
7703 // Override the incorrect alignment reported by LLVM. Clang does this as well.
7704 // On x86_64 there are some instructions like CMPXCHG16B which require this.
7705 // On all targets, integers 128 bits and above have ABI alignment of 16.
7706 // However for some targets, LLVM incorrectly reports this as 8.
7707 // See: https://github.com/ziglang/zig/issues/2987
7708 entry->abi_align = 16;
7709 entry->abi_size = align_forward(entry->abi_size, entry->abi_align);
7710 }
7711 }
7712
7713 const char u_or_i = is_signed ? 'i' : 'u';
7714 buf_resize(&entry->name, 0);
7715 buf_appendf(&entry->name, "%c%" PRIu32, u_or_i, size_in_bits);
7716
7717 entry->data.integral.is_signed = is_signed;
7718 entry->data.integral.bit_count = size_in_bits;
7719 return entry;
7720}
7721
7722uint32_t type_id_hash(TypeId const *x) {
7723 uint32_t hash = hash_combine(HASH_INIT, &x->id);
7724 switch (x->id) {
7725 case ZigTypeIdInvalid:
7726 case ZigTypeIdOpaque:
7727 case ZigTypeIdMetaType:
7728 case ZigTypeIdVoid:
7729 case ZigTypeIdBool:
7730 case ZigTypeIdUnreachable:
7731 case ZigTypeIdFloat:
7732 case ZigTypeIdStruct:
7733 case ZigTypeIdComptimeFloat:
7734 case ZigTypeIdComptimeInt:
7735 case ZigTypeIdEnumLiteral:
7736 case ZigTypeIdUndefined:
7737 case ZigTypeIdNull:
7738 case ZigTypeIdOptional:
7739 case ZigTypeIdErrorSet:
7740 case ZigTypeIdEnum:
7741 case ZigTypeIdUnion:
7742 case ZigTypeIdFn:
7743 case ZigTypeIdBoundFn:
7744 case ZigTypeIdFnFrame:
7745 case ZigTypeIdAnyFrame:
7746 zig_unreachable();
7747 case ZigTypeIdErrorUnion:
7748 hash = hash_combine(hash, &x->data.error_union.err_set_type);
7749 hash = hash_combine(hash, &x->data.error_union.payload_type);
7750 return hash;
7751 case ZigTypeIdPointer:
7752 hash = hash_combine(hash, &x->data.pointer.child_type);
7753 hash = hash_combine(hash, &x->data.pointer.ptr_len);
7754 hash = hash_combine(hash, &x->data.pointer.is_const);
7755 hash = hash_combine(hash, &x->data.pointer.is_volatile);
7756 hash = hash_combine(hash, &x->data.pointer.allow_zero);
7757 hash = hash_combine(hash, &x->data.pointer.alignment);
7758 hash = hash_combine(hash, &x->data.pointer.bit_offset_in_host);
7759 hash = hash_combine(hash, &x->data.pointer.vector_index);
7760 hash = hash_combine(hash, &x->data.pointer.host_int_bytes);
7761 if (x->data.pointer.sentinel != nullptr) {
7762 hash = hash_combine_const_val(hash, x->data.pointer.sentinel);
7763 }
7764 if (x->data.pointer.inferred_struct_field) {
7765 hash = hash_combine(hash, &x->data.pointer.inferred_struct_field->inferred_struct_type);
7766 hash = hash_combine_buf(hash, x->data.pointer.inferred_struct_field->field_name);
7767 }
7768 return hash;
7769 case ZigTypeIdArray:
7770 hash = hash_combine(hash, &x->data.array.child_type);
7771 hash = hash_combine(hash, &x->data.array.size);
7772 if (x->data.array.sentinel != nullptr) {
7773 hash = hash_combine_const_val(hash, x->data.array.sentinel);
7774 }
7775 return hash;
7776 case ZigTypeIdInt:
7777 hash = hash_combine(hash, &x->data.integer.is_signed);
7778 hash = hash_combine(hash, &x->data.integer.bit_count);
7779 return hash;
7780 case ZigTypeIdVector:
7781 hash = hash_combine(hash, &x->data.vector.elem_type);
7782 hash = hash_combine(hash, &x->data.vector.len);
7783 return hash;
7784 }
7785 zig_unreachable();
7786}
7787
7788bool type_id_eql(TypeId const *a, TypeId const *b) {
7789 if (a->id != b->id)
7790 return false;
7791 switch (a->id) {
7792 case ZigTypeIdInvalid:
7793 case ZigTypeIdMetaType:
7794 case ZigTypeIdVoid:
7795 case ZigTypeIdBool:
7796 case ZigTypeIdUnreachable:
7797 case ZigTypeIdFloat:
7798 case ZigTypeIdStruct:
7799 case ZigTypeIdComptimeFloat:
7800 case ZigTypeIdComptimeInt:
7801 case ZigTypeIdEnumLiteral:
7802 case ZigTypeIdUndefined:
7803 case ZigTypeIdNull:
7804 case ZigTypeIdOptional:
7805 case ZigTypeIdErrorSet:
7806 case ZigTypeIdEnum:
7807 case ZigTypeIdUnion:
7808 case ZigTypeIdFn:
7809 case ZigTypeIdBoundFn:
7810 case ZigTypeIdOpaque:
7811 case ZigTypeIdFnFrame:
7812 case ZigTypeIdAnyFrame:
7813 zig_unreachable();
7814 case ZigTypeIdErrorUnion:
7815 return a->data.error_union.err_set_type == b->data.error_union.err_set_type &&
7816 a->data.error_union.payload_type == b->data.error_union.payload_type;
7817
7818 case ZigTypeIdPointer:
7819 return a->data.pointer.child_type == b->data.pointer.child_type &&
7820 a->data.pointer.ptr_len == b->data.pointer.ptr_len &&
7821 a->data.pointer.is_const == b->data.pointer.is_const &&
7822 a->data.pointer.is_volatile == b->data.pointer.is_volatile &&
7823 a->data.pointer.allow_zero == b->data.pointer.allow_zero &&
7824 a->data.pointer.alignment == b->data.pointer.alignment &&
7825 a->data.pointer.bit_offset_in_host == b->data.pointer.bit_offset_in_host &&
7826 a->data.pointer.vector_index == b->data.pointer.vector_index &&
7827 a->data.pointer.host_int_bytes == b->data.pointer.host_int_bytes &&
7828 (
7829 a->data.pointer.sentinel == b->data.pointer.sentinel ||
7830 (a->data.pointer.sentinel != nullptr && b->data.pointer.sentinel != nullptr &&
7831 const_values_equal(a->data.pointer.codegen, a->data.pointer.sentinel, b->data.pointer.sentinel))
7832 ) &&
7833 (
7834 a->data.pointer.inferred_struct_field == b->data.pointer.inferred_struct_field ||
7835 (a->data.pointer.inferred_struct_field != nullptr &&
7836 b->data.pointer.inferred_struct_field != nullptr &&
7837 a->data.pointer.inferred_struct_field->inferred_struct_type ==
7838 b->data.pointer.inferred_struct_field->inferred_struct_type &&
7839 buf_eql_buf(a->data.pointer.inferred_struct_field->field_name,
7840 b->data.pointer.inferred_struct_field->field_name))
7841 );
7842 case ZigTypeIdArray:
7843 return a->data.array.child_type == b->data.array.child_type &&
7844 a->data.array.size == b->data.array.size &&
7845 (
7846 a->data.array.sentinel == b->data.array.sentinel ||
7847 (a->data.array.sentinel != nullptr && b->data.array.sentinel != nullptr &&
7848 const_values_equal(a->data.array.codegen, a->data.array.sentinel, b->data.array.sentinel))
7849 );
7850 case ZigTypeIdInt:
7851 return a->data.integer.is_signed == b->data.integer.is_signed &&
7852 a->data.integer.bit_count == b->data.integer.bit_count;
7853 case ZigTypeIdVector:
7854 return a->data.vector.elem_type == b->data.vector.elem_type &&
7855 a->data.vector.len == b->data.vector.len;
7856 }
7857 zig_unreachable();
7858}
7859
7860uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey const *x) {
7861 switch (x->id) {
7862 case ZigLLVMFnIdCtz:
7863 return (uint32_t)(x->data.ctz.bit_count) * (uint32_t)810453934 +
7864 (uint32_t)(x->data.ctz.vector_len) * (((uint32_t)x->id << 5) + 1025);
7865 case ZigLLVMFnIdClz:
7866 return (uint32_t)(x->data.clz.bit_count) * (uint32_t)2428952817 +
7867 (uint32_t)(x->data.clz.vector_len) * (((uint32_t)x->id << 5) + 1025);
7868 case ZigLLVMFnIdPopCount:
7869 return (uint32_t)(x->data.pop_count.bit_count) * (uint32_t)101195049 +
7870 (uint32_t)(x->data.pop_count.vector_len) * (((uint32_t)x->id << 5) + 1025);
7871 case ZigLLVMFnIdFloatOp:
7872 return (uint32_t)(x->data.floating.bit_count) * ((uint32_t)x->id + 1025) +
7873 (uint32_t)(x->data.floating.vector_len) * (((uint32_t)x->id << 5) + 1025) +
7874 (uint32_t)(x->data.floating.op) * (uint32_t)43789879;
7875 case ZigLLVMFnIdFMA:
7876 return (uint32_t)(x->data.floating.bit_count) * ((uint32_t)x->id + 1025) +
7877 (uint32_t)(x->data.floating.vector_len) * (((uint32_t)x->id << 5) + 1025);
7878 case ZigLLVMFnIdBswap:
7879 return (uint32_t)(x->data.bswap.bit_count) * ((uint32_t)3661994335) +
7880 (uint32_t)(x->data.bswap.vector_len) * (((uint32_t)x->id << 5) + 1025);
7881 case ZigLLVMFnIdBitReverse:
7882 return (uint32_t)(x->data.bit_reverse.bit_count) * (uint32_t)2621398431;
7883 case ZigLLVMFnIdOverflowArithmetic:
7884 return ((uint32_t)(x->data.overflow_arithmetic.bit_count) * 87135777) +
7885 ((uint32_t)(x->data.overflow_arithmetic.add_sub_mul) * 31640542) +
7886 ((uint32_t)(x->data.overflow_arithmetic.is_signed) ? 1062315172 : 314955820) +
7887 x->data.overflow_arithmetic.vector_len * 1435156945;
7888 }
7889 zig_unreachable();
7890}
7891
7892bool zig_llvm_fn_key_eql(ZigLLVMFnKey const *a, ZigLLVMFnKey const *b) {
7893 if (a->id != b->id)
7894 return false;
7895 switch (a->id) {
7896 case ZigLLVMFnIdCtz:
7897 return a->data.ctz.bit_count == b->data.ctz.bit_count;
7898 case ZigLLVMFnIdClz:
7899 return a->data.clz.bit_count == b->data.clz.bit_count;
7900 case ZigLLVMFnIdPopCount:
7901 return a->data.pop_count.bit_count == b->data.pop_count.bit_count;
7902 case ZigLLVMFnIdBswap:
7903 return a->data.bswap.bit_count == b->data.bswap.bit_count &&
7904 a->data.bswap.vector_len == b->data.bswap.vector_len;
7905 case ZigLLVMFnIdBitReverse:
7906 return a->data.bit_reverse.bit_count == b->data.bit_reverse.bit_count;
7907 case ZigLLVMFnIdFloatOp:
7908 return a->data.floating.bit_count == b->data.floating.bit_count &&
7909 a->data.floating.vector_len == b->data.floating.vector_len &&
7910 a->data.floating.op == b->data.floating.op;
7911 case ZigLLVMFnIdFMA:
7912 return a->data.floating.bit_count == b->data.floating.bit_count &&
7913 a->data.floating.vector_len == b->data.floating.vector_len;
7914 case ZigLLVMFnIdOverflowArithmetic:
7915 return (a->data.overflow_arithmetic.bit_count == b->data.overflow_arithmetic.bit_count) &&
7916 (a->data.overflow_arithmetic.add_sub_mul == b->data.overflow_arithmetic.add_sub_mul) &&
7917 (a->data.overflow_arithmetic.is_signed == b->data.overflow_arithmetic.is_signed) &&
7918 (a->data.overflow_arithmetic.vector_len == b->data.overflow_arithmetic.vector_len);
7919 }
7920 zig_unreachable();
7921}
7922
7923static void init_const_undefined(CodeGen *g, ZigValue *const_val) {
7924 Error err;
7925 ZigType *wanted_type = const_val->type;
7926 if (wanted_type->id == ZigTypeIdArray) {
7927 const_val->special = ConstValSpecialStatic;
7928 const_val->data.x_array.special = ConstArraySpecialUndef;
7929 } else if (wanted_type->id == ZigTypeIdStruct) {
7930 if ((err = type_resolve(g, wanted_type, ResolveStatusZeroBitsKnown))) {
7931 return;
7932 }
7933
7934 const_val->special = ConstValSpecialStatic;
7935 size_t field_count = wanted_type->data.structure.src_field_count;
7936 const_val->data.x_struct.fields = alloc_const_vals_ptrs(g, field_count);
7937 for (size_t i = 0; i < field_count; i += 1) {
7938 TypeStructField *field = wanted_type->data.structure.fields[i];
7939 if (field->is_comptime) {
7940 // Comptime fields are part of the type, and do not need to
7941 // be initialized.
7942 continue;
7943 }
7944
7945 ZigValue *field_val = const_val->data.x_struct.fields[i];
7946 field_val->type = resolve_struct_field_type(g, wanted_type->data.structure.fields[i]);
7947 assert(field_val->type);
7948 init_const_undefined(g, field_val);
7949 field_val->parent.id = ConstParentIdStruct;
7950 field_val->parent.data.p_struct.struct_val = const_val;
7951 field_val->parent.data.p_struct.field_index = i;
7952 }
7953 } else {
7954 const_val->special = ConstValSpecialUndef;
7955 }
7956}
7957
7958void expand_undef_struct(CodeGen *g, ZigValue *const_val) {
7959 if (const_val->special == ConstValSpecialUndef) {
7960 init_const_undefined(g, const_val);
7961 }
7962}
7963
7964// Canonicalize the array value as ConstArraySpecialNone
7965void expand_undef_array(CodeGen *g, ZigValue *const_val) {
7966 size_t elem_count;
7967 ZigType *elem_type;
7968 if (const_val->type->id == ZigTypeIdArray) {
7969 elem_count = const_val->type->data.array.len;
7970 elem_type = const_val->type->data.array.child_type;
7971 } else if (const_val->type->id == ZigTypeIdVector) {
7972 elem_count = const_val->type->data.vector.len;
7973 elem_type = const_val->type->data.vector.elem_type;
7974 } else {
7975 zig_unreachable();
7976 }
7977 if (const_val->special == ConstValSpecialUndef) {
7978 const_val->special = ConstValSpecialStatic;
7979 const_val->data.x_array.special = ConstArraySpecialUndef;
7980 }
7981 switch (const_val->data.x_array.special) {
7982 case ConstArraySpecialNone:
7983 return;
7984 case ConstArraySpecialUndef: {
7985 const_val->data.x_array.special = ConstArraySpecialNone;
7986 const_val->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(elem_count);
7987 for (size_t i = 0; i < elem_count; i += 1) {
7988 ZigValue *element_val = &const_val->data.x_array.data.s_none.elements[i];
7989 element_val->type = elem_type;
7990 init_const_undefined(g, element_val);
7991 element_val->parent.id = ConstParentIdArray;
7992 element_val->parent.data.p_array.array_val = const_val;
7993 element_val->parent.data.p_array.elem_index = i;
7994 }
7995 return;
7996 }
7997 case ConstArraySpecialBuf: {
7998 Buf *buf = const_val->data.x_array.data.s_buf;
7999 // If we're doing this it means that we are potentially modifying the data,
8000 // so we can't have it be in the string literals table
8001 g->string_literals_table.maybe_remove(buf);
8002
8003 const_val->data.x_array.special = ConstArraySpecialNone;
8004 assert(elem_count == buf_len(buf));
8005 const_val->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(elem_count);
8006 for (size_t i = 0; i < elem_count; i += 1) {
8007 ZigValue *this_char = &const_val->data.x_array.data.s_none.elements[i];
8008 this_char->special = ConstValSpecialStatic;
8009 this_char->type = g->builtin_types.entry_u8;
8010 bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(buf)[i]);
8011 this_char->parent.id = ConstParentIdArray;
8012 this_char->parent.data.p_array.array_val = const_val;
8013 this_char->parent.data.p_array.elem_index = i;
8014 }
8015 return;
8016 }
8017 }
8018 zig_unreachable();
8019}
8020
8021static const ZigTypeId all_type_ids[] = {
8022 ZigTypeIdMetaType,
8023 ZigTypeIdVoid,
8024 ZigTypeIdBool,
8025 ZigTypeIdUnreachable,
8026 ZigTypeIdInt,
8027 ZigTypeIdFloat,
8028 ZigTypeIdPointer,
8029 ZigTypeIdArray,
8030 ZigTypeIdStruct,
8031 ZigTypeIdComptimeFloat,
8032 ZigTypeIdComptimeInt,
8033 ZigTypeIdUndefined,
8034 ZigTypeIdNull,
8035 ZigTypeIdOptional,
8036 ZigTypeIdErrorUnion,
8037 ZigTypeIdErrorSet,
8038 ZigTypeIdEnum,
8039 ZigTypeIdUnion,
8040 ZigTypeIdFn,
8041 ZigTypeIdBoundFn,
8042 ZigTypeIdOpaque,
8043 ZigTypeIdFnFrame,
8044 ZigTypeIdAnyFrame,
8045 ZigTypeIdVector,
8046 ZigTypeIdEnumLiteral,
8047};
8048
8049ZigTypeId type_id_at_index(size_t index) {
8050 assert(index < array_length(all_type_ids));
8051 return all_type_ids[index];
8052}
8053
8054size_t type_id_len() {
8055 return array_length(all_type_ids);
8056}
8057
8058size_t type_id_index(ZigType *entry) {
8059 switch (entry->id) {
8060 case ZigTypeIdInvalid:
8061 zig_unreachable();
8062 case ZigTypeIdMetaType:
8063 return 0;
8064 case ZigTypeIdVoid:
8065 return 1;
8066 case ZigTypeIdBool:
8067 return 2;
8068 case ZigTypeIdUnreachable:
8069 return 3;
8070 case ZigTypeIdInt:
8071 return 4;
8072 case ZigTypeIdFloat:
8073 return 5;
8074 case ZigTypeIdPointer:
8075 return 6;
8076 case ZigTypeIdArray:
8077 return 7;
8078 case ZigTypeIdStruct:
8079 if (entry->data.structure.special == StructSpecialSlice)
8080 return 6;
8081 return 8;
8082 case ZigTypeIdComptimeFloat:
8083 return 9;
8084 case ZigTypeIdComptimeInt:
8085 return 10;
8086 case ZigTypeIdUndefined:
8087 return 11;
8088 case ZigTypeIdNull:
8089 return 12;
8090 case ZigTypeIdOptional:
8091 return 13;
8092 case ZigTypeIdErrorUnion:
8093 return 14;
8094 case ZigTypeIdErrorSet:
8095 return 15;
8096 case ZigTypeIdEnum:
8097 return 16;
8098 case ZigTypeIdUnion:
8099 return 17;
8100 case ZigTypeIdFn:
8101 return 18;
8102 case ZigTypeIdBoundFn:
8103 return 19;
8104 case ZigTypeIdOpaque:
8105 return 20;
8106 case ZigTypeIdFnFrame:
8107 return 21;
8108 case ZigTypeIdAnyFrame:
8109 return 22;
8110 case ZigTypeIdVector:
8111 return 23;
8112 case ZigTypeIdEnumLiteral:
8113 return 24;
8114 }
8115 zig_unreachable();
8116}
8117
8118const char *type_id_name(ZigTypeId id) {
8119 switch (id) {
8120 case ZigTypeIdInvalid:
8121 zig_unreachable();
8122 case ZigTypeIdMetaType:
8123 return "Type";
8124 case ZigTypeIdVoid:
8125 return "Void";
8126 case ZigTypeIdBool:
8127 return "Bool";
8128 case ZigTypeIdUnreachable:
8129 return "NoReturn";
8130 case ZigTypeIdInt:
8131 return "Int";
8132 case ZigTypeIdFloat:
8133 return "Float";
8134 case ZigTypeIdPointer:
8135 return "Pointer";
8136 case ZigTypeIdArray:
8137 return "Array";
8138 case ZigTypeIdStruct:
8139 return "Struct";
8140 case ZigTypeIdComptimeFloat:
8141 return "ComptimeFloat";
8142 case ZigTypeIdComptimeInt:
8143 return "ComptimeInt";
8144 case ZigTypeIdEnumLiteral:
8145 return "EnumLiteral";
8146 case ZigTypeIdUndefined:
8147 return "Undefined";
8148 case ZigTypeIdNull:
8149 return "Null";
8150 case ZigTypeIdOptional:
8151 return "Optional";
8152 case ZigTypeIdErrorUnion:
8153 return "ErrorUnion";
8154 case ZigTypeIdErrorSet:
8155 return "ErrorSet";
8156 case ZigTypeIdEnum:
8157 return "Enum";
8158 case ZigTypeIdUnion:
8159 return "Union";
8160 case ZigTypeIdFn:
8161 return "Fn";
8162 case ZigTypeIdBoundFn:
8163 return "BoundFn";
8164 case ZigTypeIdOpaque:
8165 return "Opaque";
8166 case ZigTypeIdVector:
8167 return "Vector";
8168 case ZigTypeIdFnFrame:
8169 return "Frame";
8170 case ZigTypeIdAnyFrame:
8171 return "AnyFrame";
8172 }
8173 zig_unreachable();
8174}
8175
8176ZigType *get_align_amt_type(CodeGen *g) {
8177 if (g->align_amt_type == nullptr) {
8178 // according to LLVM the maximum alignment is 1 << 29.
8179 g->align_amt_type = get_int_type(g, false, 29);
8180 }
8181 return g->align_amt_type;
8182}
8183
8184uint32_t type_ptr_hash(const ZigType *ptr) {
8185 return hash_combine(HASH_INIT, &ptr);
8186}
8187
8188bool type_ptr_eql(const ZigType *a, const ZigType *b) {
8189 return a == b;
8190}
8191
8192uint32_t pkg_ptr_hash(const ZigPackage *ptr) {
8193 return hash_combine(HASH_INIT, &ptr);
8194}
8195
8196bool pkg_ptr_eql(const ZigPackage *a, const ZigPackage *b) {
8197 return a == b;
8198}
8199
8200uint32_t tld_ptr_hash(const Tld *ptr) {
8201 return hash_combine(HASH_INIT, &ptr);
8202}
8203
8204bool tld_ptr_eql(const Tld *a, const Tld *b) {
8205 return a == b;
8206}
8207
8208uint32_t node_ptr_hash(const AstNode *ptr) {
8209 return hash_combine(HASH_INIT, &ptr);
8210}
8211
8212bool node_ptr_eql(const AstNode *a, const AstNode *b) {
8213 return a == b;
8214}
8215
8216uint32_t fn_ptr_hash(const ZigFn *ptr) {
8217 return hash_combine(HASH_INIT, &ptr);
8218}
8219
8220bool fn_ptr_eql(const ZigFn *a, const ZigFn *b) {
8221 return a == b;
8222}
8223
8224uint32_t err_ptr_hash(const ErrorTableEntry *ptr) {
8225 return hash_combine(HASH_INIT, &ptr);
8226}
8227
8228bool err_ptr_eql(const ErrorTableEntry *a, const ErrorTableEntry *b) {
8229 return a == b;
8230}
8231
8232ZigValue *get_builtin_value(CodeGen *codegen, const char *name) {
8233 Buf *buf_name = buf_create_from_str(name);
8234
8235 ScopeDecls *builtin_scope = get_container_scope(codegen->std_builtin_import);
8236 Tld *tld = find_container_decl(codegen, builtin_scope, buf_name);
8237 assert(tld != nullptr);
8238 resolve_top_level_decl(codegen, tld, nullptr, false);
8239 assert(tld->id == TldIdVar && tld->resolution == TldResolutionOk);
8240 TldVar *tld_var = (TldVar *)tld;
8241 ZigValue *var_value = tld_var->var->const_value;
8242 assert(var_value != nullptr);
8243
8244 buf_destroy(buf_name);
8245 return var_value;
8246}
8247
8248ZigType *get_builtin_type(CodeGen *codegen, const char *name) {
8249 ZigValue *type_val = get_builtin_value(codegen, name);
8250 assert(type_val->type->id == ZigTypeIdMetaType);
8251 return type_val->data.x_type;
8252}
8253
8254bool type_is_global_error_set(ZigType *err_set_type) {
8255 assert(err_set_type->id == ZigTypeIdErrorSet);
8256 assert(!err_set_type->data.error_set.incomplete);
8257 return err_set_type->data.error_set.err_count == UINT32_MAX;
8258}
8259
8260bool type_can_fail(ZigType *type_entry) {
8261 return type_entry->id == ZigTypeIdErrorUnion || type_entry->id == ZigTypeIdErrorSet;
8262}
8263
8264bool fn_type_can_fail(FnTypeId *fn_type_id) {
8265 return type_can_fail(fn_type_id->return_type);
8266}
8267
8268// ErrorNone - result pointer has the type
8269// ErrorOverflow - an integer primitive type has too large a bit width
8270// ErrorPrimitiveTypeNotFound - result pointer unchanged
8271Error get_primitive_type(CodeGen *g, Buf *name, ZigType **result) {
8272 if (buf_len(name) >= 2) {
8273 uint8_t first_c = buf_ptr(name)[0];
8274 if (first_c == 'i' || first_c == 'u') {
8275 for (size_t i = 1; i < buf_len(name); i += 1) {
8276 uint8_t c = buf_ptr(name)[i];
8277 if (c < '0' || c > '9') {
8278 goto not_integer;
8279 }
8280 }
8281 bool is_signed = (first_c == 'i');
8282 unsigned long int bit_count = strtoul(buf_ptr(name) + 1, nullptr, 10);
8283 // strtoul returns ULONG_MAX on errors, so this comparison catches that as well.
8284 if (bit_count >= 65536) return ErrorOverflow;
8285 *result = get_int_type(g, is_signed, bit_count);
8286 return ErrorNone;
8287 }
8288 }
8289
8290not_integer:
8291
8292 auto primitive_table_entry = g->primitive_type_table.maybe_get(name);
8293 if (primitive_table_entry == nullptr)
8294 return ErrorPrimitiveTypeNotFound;
8295
8296 *result = primitive_table_entry->value;
8297 return ErrorNone;
8298}
8299
8300Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents_buf) {
8301 size_t len;
8302 const char *contents = stage2_fetch_file(&g->stage1, buf_ptr(resolved_path), buf_len(resolved_path), &len);
8303 if (contents == nullptr)
8304 return ErrorFileNotFound;
8305 buf_init_from_mem(contents_buf, contents, len);
8306 return ErrorNone;
8307}
8308
8309static X64CABIClass type_windows_abi_x86_64_class(CodeGen *g, ZigType *ty, size_t ty_size) {
8310 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017
8311 switch (ty_size) {
8312 case 1:
8313 case 2:
8314 case 4:
8315 case 8:
8316 break;
8317 case 16:
8318 return (ty->id == ZigTypeIdVector) ? X64CABIClass_SSE : X64CABIClass_MEMORY;
8319 default:
8320 return X64CABIClass_MEMORY;
8321 }
8322 switch (ty->id) {
8323 case ZigTypeIdInvalid:
8324 case ZigTypeIdMetaType:
8325 case ZigTypeIdComptimeFloat:
8326 case ZigTypeIdComptimeInt:
8327 case ZigTypeIdNull:
8328 case ZigTypeIdUndefined:
8329 case ZigTypeIdBoundFn:
8330 case ZigTypeIdOpaque:
8331 case ZigTypeIdEnumLiteral:
8332 zig_unreachable();
8333
8334 case ZigTypeIdFn:
8335 case ZigTypeIdPointer:
8336 case ZigTypeIdInt:
8337 case ZigTypeIdBool:
8338 case ZigTypeIdEnum:
8339 case ZigTypeIdVoid:
8340 case ZigTypeIdUnreachable:
8341 case ZigTypeIdErrorSet:
8342 case ZigTypeIdErrorUnion:
8343 case ZigTypeIdStruct:
8344 case ZigTypeIdUnion:
8345 case ZigTypeIdOptional:
8346 case ZigTypeIdFnFrame:
8347 case ZigTypeIdAnyFrame:
8348 return X64CABIClass_INTEGER;
8349
8350 case ZigTypeIdFloat:
8351 case ZigTypeIdVector:
8352 return X64CABIClass_SSE;
8353
8354 case ZigTypeIdArray:
8355 return X64CABIClass_Unknown;
8356 }
8357 zig_unreachable();
8358}
8359
8360static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size_t ty_size) {
8361 switch (ty->id) {
8362 case ZigTypeIdEnum:
8363 case ZigTypeIdInt:
8364 case ZigTypeIdBool:
8365 return X64CABIClass_INTEGER;
8366 case ZigTypeIdFloat:
8367 case ZigTypeIdVector:
8368 return X64CABIClass_SSE;
8369 case ZigTypeIdStruct: {
8370 // "If the size of an object is larger than four eightbytes, or it contains unaligned
8371 // fields, it has class MEMORY"
8372 if (ty_size > 32)
8373 return X64CABIClass_MEMORY;
8374 if (ty->data.structure.layout != ContainerLayoutExtern) {
8375 // TODO determine whether packed structs have any unaligned fields
8376 return X64CABIClass_Unknown;
8377 }
8378 // "If the size of the aggregate exceeds two eightbytes and the first eight-
8379 // byte isn’t SSE or any other eightbyte isn’t SSEUP, the whole argument
8380 // is passed in memory."
8381 if (ty_size > 16) {
8382 // Zig doesn't support vectors and large fp registers yet, so this will always
8383 // be memory.
8384 return X64CABIClass_MEMORY;
8385 }
8386 // "If the size of the aggregate exceeds a single eightbyte, each is classified
8387 // separately.".
8388 // "If one of the classes is MEMORY, the whole argument is passed in memory"
8389 X64CABIClass working_class = X64CABIClass_Unknown;
8390 for (uint32_t i = 0; i < ty->data.structure.src_field_count; i += 1) {
8391 X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.structure.fields[0]->type_entry);
8392 if (field_class == X64CABIClass_Unknown)
8393 return X64CABIClass_Unknown;
8394 if (i == 0 || field_class == X64CABIClass_MEMORY || working_class == X64CABIClass_SSE) {
8395 working_class = field_class;
8396 }
8397 }
8398 if (working_class == X64CABIClass_MEMORY) {
8399 return X64CABIClass_MEMORY;
8400 }
8401 return X64CABIClass_AGG;
8402 }
8403 case ZigTypeIdUnion: {
8404 // "If the size of an object is larger than four eightbytes, or it contains unaligned
8405 // fields, it has class MEMORY"
8406 if (ty_size > 32)
8407 return X64CABIClass_MEMORY;
8408 if (ty->data.unionation.layout != ContainerLayoutExtern)
8409 return X64CABIClass_MEMORY;
8410 // "If the size of the aggregate exceeds two eightbytes and the first eight-
8411 // byte isn’t SSE or any other eightbyte isn’t SSEUP, the whole argument
8412 // is passed in memory."
8413 if (ty_size > 16) {
8414 // Zig doesn't support vectors and large fp registers yet, so this will always
8415 // be memory.
8416 return X64CABIClass_MEMORY;
8417 }
8418 X64CABIClass working_class = X64CABIClass_Unknown;
8419 for (uint32_t i = 0; i < ty->data.unionation.src_field_count; i += 1) {
8420 X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.unionation.fields->type_entry);
8421 if (field_class == X64CABIClass_Unknown)
8422 return X64CABIClass_Unknown;
8423 if (i == 0 || field_class == X64CABIClass_MEMORY || field_class == X64CABIClass_INTEGER || working_class == X64CABIClass_SSE) {
8424 working_class = field_class;
8425 }
8426 }
8427 return working_class;
8428 }
8429 default:
8430 return X64CABIClass_Unknown;
8431 }
8432}
8433
8434X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
8435 Error err;
8436 const size_t ty_size = type_size(g, ty);
8437
8438 if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {
8439 return type_windows_abi_x86_64_class(g, ty, ty_size);
8440 }
8441
8442 ZigType *ptr_type;
8443 if ((err = get_codegen_ptr_type(g, ty, &ptr_type))) return X64CABIClass_Unknown;
8444 if (ptr_type != nullptr)
8445 return X64CABIClass_INTEGER;
8446
8447 if (g->zig_target->arch == ZigLLVM_aarch64 ||
8448 g->zig_target->arch == ZigLLVM_aarch64_be)
8449 {
8450 X64CABIClass result = type_system_V_abi_x86_64_class(g, ty, ty_size);
8451 return (result == X64CABIClass_MEMORY) ? X64CABIClass_MEMORY_nobyval : result;
8452 } else {
8453 return type_system_V_abi_x86_64_class(g, ty, ty_size);
8454 }
8455}
8456
8457// NOTE this does not depend on x86_64
8458Error type_is_c_abi_int(CodeGen *g, ZigType *ty, bool *result) {
8459 if (ty->id == ZigTypeIdInt ||
8460 ty->id == ZigTypeIdFloat ||
8461 ty->id == ZigTypeIdBool ||
8462 ty->id == ZigTypeIdEnum ||
8463 ty->id == ZigTypeIdVoid ||
8464 ty->id == ZigTypeIdUnreachable)
8465 {
8466 *result = true;
8467 return ErrorNone;
8468 }
8469
8470 Error err;
8471 ZigType *ptr_type;
8472 if ((err = get_codegen_ptr_type(g, ty, &ptr_type))) return err;
8473 *result = ptr_type != nullptr;
8474 return ErrorNone;
8475}
8476
8477bool type_is_c_abi_int_bail(CodeGen *g, ZigType *ty) {
8478 Error err;
8479 bool result;
8480 if ((err = type_is_c_abi_int(g, ty, &result)))
8481 codegen_report_errors_and_exit(g);
8482
8483 return result;
8484}
8485
8486uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field) {
8487 assert(struct_type->id == ZigTypeIdStruct);
8488 if (struct_type->data.structure.layout != ContainerLayoutAuto) {
8489 assert(type_is_resolved(struct_type, ResolveStatusSizeKnown));
8490 }
8491 if (struct_type->data.structure.host_int_bytes == nullptr)
8492 return 0;
8493 return struct_type->data.structure.host_int_bytes[field->gen_index];
8494}
8495
8496Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
8497 ZigValue *const_val, ZigType *wanted_type)
8498{
8499 ZigValue ptr_val = {};
8500 ptr_val.special = ConstValSpecialStatic;
8501 ptr_val.type = get_pointer_to_type(codegen, wanted_type, true);
8502 ptr_val.data.x_ptr.mut = ConstPtrMutComptimeConst;
8503 ptr_val.data.x_ptr.special = ConstPtrSpecialRef;
8504 ptr_val.data.x_ptr.data.ref.pointee = const_val;
8505 if (const_ptr_pointee(ira, codegen, &ptr_val, source_node) == nullptr)
8506 return ErrorSemanticAnalyzeFail;
8507
8508 return ErrorNone;
8509}
8510
8511const char *container_string(ContainerKind kind) {
8512 switch (kind) {
8513 case ContainerKindEnum: return "enum";
8514 case ContainerKindStruct: return "struct";
8515 case ContainerKindUnion: return "union";
8516 case ContainerKindOpaque: return "opaque";
8517 }
8518 zig_unreachable();
8519}
8520
8521bool ptr_allows_addr_zero(ZigType *ptr_type) {
8522 if (ptr_type->id == ZigTypeIdPointer) {
8523 return ptr_type->data.pointer.allow_zero;
8524 } else if (ptr_type->id == ZigTypeIdOptional) {
8525 return true;
8526 }
8527 return false;
8528}
8529
8530Buf *type_bare_name(ZigType *type_entry) {
8531 if (is_slice(type_entry)) {
8532 return &type_entry->name;
8533 } else if (is_container(type_entry)) {
8534 return get_container_scope(type_entry)->bare_name;
8535 } else {
8536 return &type_entry->name;
8537 }
8538}
8539
8540// TODO this will have to be more clever, probably using the full name
8541// and replacing '.' with '_' or something like that
8542Buf *type_h_name(ZigType *t) {
8543 return type_bare_name(t);
8544}
8545
8546static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
8547 if (type->data.structure.resolve_status >= wanted_resolve_status) return;
8548
8549 ZigType *ptr_type = type->data.structure.fields[slice_ptr_index]->type_entry;
8550 ZigType *child_type = ptr_type->data.pointer.child_type;
8551 ZigType *usize_type = g->builtin_types.entry_usize;
8552
8553 bool done = false;
8554 if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
8555 ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero ||
8556 ptr_type->data.pointer.sentinel != nullptr)
8557 {
8558 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
8559 PtrLenUnknown, 0, 0, 0, false);
8560 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);
8561
8562 assertNoError(type_resolve(g, peer_slice_type, wanted_resolve_status));
8563 type->llvm_type = peer_slice_type->llvm_type;
8564 type->llvm_di_type = peer_slice_type->llvm_di_type;
8565 type->data.structure.resolve_status = peer_slice_type->data.structure.resolve_status;
8566 done = true;
8567 }
8568
8569 // If the child type is []const T then we need to make sure the type ref
8570 // and debug info is the same as if the child type were []T.
8571 if (is_slice(child_type)) {
8572 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index]->type_entry;
8573 assert(child_ptr_type->id == ZigTypeIdPointer);
8574 if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||
8575 child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero ||
8576 child_ptr_type->data.pointer.sentinel != nullptr)
8577 {
8578 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
8579 ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,
8580 PtrLenUnknown, 0, 0, 0, false);
8581 ZigType *bland_child_slice = get_slice_type(g, bland_child_ptr_type);
8582 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, bland_child_slice, false, false,
8583 PtrLenUnknown, 0, 0, 0, false);
8584 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);
8585
8586 assertNoError(type_resolve(g, peer_slice_type, wanted_resolve_status));
8587 type->llvm_type = peer_slice_type->llvm_type;
8588 type->llvm_di_type = peer_slice_type->llvm_di_type;
8589 type->data.structure.resolve_status = peer_slice_type->data.structure.resolve_status;
8590 done = true;
8591 }
8592 }
8593
8594 if (done) return;
8595
8596 LLVMTypeRef usize_llvm_type = get_llvm_type(g, usize_type);
8597 ZigLLVMDIType *usize_llvm_di_type = get_llvm_di_type(g, usize_type);
8598 ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
8599 ZigLLVMDIFile *di_file = nullptr;
8600 unsigned line = 0;
8601
8602 if (type->data.structure.resolve_status < ResolveStatusLLVMFwdDecl) {
8603 type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&type->name));
8604
8605 type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
8606 ZigLLVMTag_DW_structure_type(), buf_ptr(&type->name),
8607 compile_unit_scope, di_file, line);
8608
8609 type->data.structure.resolve_status = ResolveStatusLLVMFwdDecl;
8610 if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return;
8611 }
8612
8613 if (!type_has_bits(g, child_type)) {
8614 LLVMTypeRef element_types[] = {
8615 usize_llvm_type,
8616 };
8617 LLVMStructSetBody(type->llvm_type, element_types, 1, false);
8618
8619 uint64_t len_debug_size_in_bits = usize_type->size_in_bits;
8620 uint64_t len_debug_align_in_bits = 8*usize_type->abi_align;
8621 uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type, 0);
8622
8623 uint64_t debug_size_in_bits = type->size_in_bits;
8624 uint64_t debug_align_in_bits = 8*type->abi_align;
8625
8626 ZigLLVMDIType *di_element_types[] = {
8627 ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type),
8628 "len", di_file, line,
8629 len_debug_size_in_bits,
8630 len_debug_align_in_bits,
8631 len_offset_in_bits,
8632 ZigLLVM_DIFlags_Zero,
8633 usize_llvm_di_type),
8634 };
8635 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
8636 compile_unit_scope,
8637 buf_ptr(&type->name),
8638 di_file, line, debug_size_in_bits, debug_align_in_bits,
8639 ZigLLVM_DIFlags_Zero,
8640 nullptr, di_element_types, 1, 0, nullptr, "");
8641
8642 ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type);
8643 type->llvm_di_type = replacement_di_type;
8644 type->data.structure.resolve_status = ResolveStatusLLVMFull;
8645 return;
8646 }
8647
8648 LLVMTypeRef element_types[2];
8649 element_types[slice_ptr_index] = get_llvm_type(g, ptr_type);
8650 element_types[slice_len_index] = get_llvm_type(g, g->builtin_types.entry_usize);
8651 if (type->data.structure.resolve_status >= wanted_resolve_status) return;
8652 LLVMStructSetBody(type->llvm_type, element_types, 2, false);
8653
8654 uint64_t ptr_debug_size_in_bits = ptr_type->size_in_bits;
8655 uint64_t ptr_debug_align_in_bits = 8*ptr_type->abi_align;
8656 uint64_t ptr_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type, 0);
8657
8658 uint64_t len_debug_size_in_bits = usize_type->size_in_bits;
8659 uint64_t len_debug_align_in_bits = 8*usize_type->abi_align;
8660 uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type, 1);
8661
8662 uint64_t debug_size_in_bits = type->size_in_bits;
8663 uint64_t debug_align_in_bits = 8*type->abi_align;
8664
8665 ZigLLVMDIType *di_element_types[] = {
8666 ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type),
8667 "ptr", di_file, line,
8668 ptr_debug_size_in_bits,
8669 ptr_debug_align_in_bits,
8670 ptr_offset_in_bits,
8671 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_type)),
8672 ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type),
8673 "len", di_file, line,
8674 len_debug_size_in_bits,
8675 len_debug_align_in_bits,
8676 len_offset_in_bits,
8677 ZigLLVM_DIFlags_Zero, usize_llvm_di_type),
8678 };
8679 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
8680 compile_unit_scope,
8681 buf_ptr(&type->name),
8682 di_file, line, debug_size_in_bits, debug_align_in_bits,
8683 ZigLLVM_DIFlags_Zero,
8684 nullptr, di_element_types, 2, 0, nullptr, "");
8685
8686 ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type);
8687 type->llvm_di_type = replacement_di_type;
8688 type->data.structure.resolve_status = ResolveStatusLLVMFull;
8689}
8690
8691static LLVMTypeRef get_llvm_type_of_n_bytes(unsigned byte_size) {
8692 return byte_size == 1 ?
8693 LLVMInt8Type() : LLVMArrayType(LLVMInt8Type(), byte_size);
8694}
8695
8696static LLVMTypeRef llvm_int_for_size(size_t size) {
8697 if (size > 4) {
8698 return LLVMInt64Type();
8699 } else if (size > 2) {
8700 return LLVMInt32Type();
8701 } else if (size == 2) {
8702 return LLVMInt16Type();
8703 } else {
8704 return LLVMInt8Type();
8705 }
8706}
8707
8708static LLVMTypeRef llvm_sse_for_size(size_t size) {
8709 if (size > 4)
8710 return LLVMDoubleType();
8711 else
8712 return LLVMFloatType();
8713}
8714
8715// Since it's not possible to control calling convention or register
8716// allocation in LLVM, clang seems to use intermediate types to manipulate
8717// LLVM into doing the right thing. It uses a float to force SSE registers,
8718// and a struct when 2 registers must be used. Some examples:
8719// { f32 } -> float
8720// { f32, i32 } -> { float, i32 }
8721// { i32, i32, f32 } -> { i64, float }
8722//
8723// The implementation below does not match clang 1:1. For instance, clang
8724// uses `<2x float>` while we generate `double`. There's a lot more edge
8725// cases and complexity when converting back and forth in clang though,
8726// so below is the simplest implementation that passes all tests.
8727static Error resolve_llvm_c_abi_type(CodeGen *g, ZigType *ty) {
8728 size_t ty_size = type_size(g, ty);
8729 LLVMTypeRef abi_type;
8730 switch (ty->id) {
8731 case ZigTypeIdEnum:
8732 case ZigTypeIdInt:
8733 case ZigTypeIdBool:
8734 abi_type = llvm_int_for_size(ty_size);
8735 break;
8736 case ZigTypeIdFloat:
8737 case ZigTypeIdVector:
8738 abi_type = llvm_sse_for_size(ty_size);
8739 break;
8740 case ZigTypeIdStruct: {
8741 uint32_t eightbyte_index = 0;
8742 size_t type_sizes[] = {0, 0};
8743 X64CABIClass type_classes[] = {X64CABIClass_Unknown, X64CABIClass_Unknown};
8744 for (uint32_t i = 0; i < ty->data.structure.src_field_count; i += 1) {
8745 if (ty->data.structure.fields[i]->offset >= 8) {
8746 eightbyte_index = 1;
8747 }
8748 ZigType *field_ty = ty->data.structure.fields[i]->type_entry;
8749 X64CABIClass field_class = type_c_abi_x86_64_class(g, field_ty);
8750
8751 if (field_class == X64CABIClass_INTEGER) {
8752 type_classes[eightbyte_index] = X64CABIClass_INTEGER;
8753 } else if (type_classes[eightbyte_index] == X64CABIClass_Unknown) {
8754 type_classes[eightbyte_index] = field_class;
8755 }
8756 if (field_ty->abi_size > 8) {
8757 assert(eightbyte_index == 0);
8758 type_sizes[0] = 8;
8759 type_sizes[1] = field_ty->abi_size - 8;
8760 type_classes[1] = type_classes[0];
8761 eightbyte_index = 1;
8762 } else {
8763 type_sizes[eightbyte_index] += field_ty->abi_size;
8764 }
8765 }
8766
8767 LLVMTypeRef return_elem_types[] = {
8768 LLVMVoidType(),
8769 LLVMVoidType(),
8770 };
8771 for (uint32_t i = 0; i <= eightbyte_index; i += 1) {
8772 if (type_classes[i] == X64CABIClass_INTEGER) {
8773 return_elem_types[i] = llvm_int_for_size(type_sizes[i]);
8774 } else {
8775 return_elem_types[i] = llvm_sse_for_size(type_sizes[i]);
8776 }
8777 }
8778 if (eightbyte_index == 0) {
8779 abi_type = return_elem_types[0];
8780 } else {
8781 abi_type = LLVMStructType(return_elem_types, 2, false);
8782 }
8783 break;
8784 }
8785 case ZigTypeIdUnion:
8786 default:
8787 // currently unreachable
8788 zig_panic("TODO: support C ABI unions");
8789 }
8790 ty->llvm_c_abi_type = abi_type;
8791 return ErrorNone;
8792}
8793
8794static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveStatus wanted_resolve_status,
8795 ZigType *async_frame_type)
8796{
8797 assert(struct_type->id == ZigTypeIdStruct);
8798 assert(struct_type->data.structure.resolve_status != ResolveStatusInvalid);
8799 assert(struct_type->data.structure.resolve_status >= ResolveStatusSizeKnown);
8800 assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0);
8801 if (struct_type->data.structure.resolve_status >= wanted_resolve_status) return;
8802
8803 AstNode *decl_node = struct_type->data.structure.decl_node;
8804 ZigLLVMDIFile *di_file;
8805 ZigLLVMDIScope *di_scope;
8806 unsigned line;
8807 if (decl_node != nullptr) {
8808 Scope *scope = &struct_type->data.structure.decls_scope->base;
8809 ZigType *import = get_scope_import(scope);
8810 di_file = import->data.structure.root_struct->di_file;
8811 di_scope = ZigLLVMFileToScope(di_file);
8812 line = node_line_onebased(decl_node);
8813 } else {
8814 di_file = nullptr;
8815 di_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
8816 line = 0;
8817 }
8818
8819 if (struct_type->data.structure.resolve_status < ResolveStatusLLVMFwdDecl) {
8820 struct_type->llvm_type = type_has_bits(g, struct_type) ?
8821 LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&struct_type->name)) : LLVMVoidType();
8822 unsigned dwarf_kind = ZigLLVMTag_DW_structure_type();
8823 struct_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
8824 dwarf_kind, buf_ptr(&struct_type->name),
8825 di_scope, di_file, line);
8826
8827 struct_type->data.structure.resolve_status = ResolveStatusLLVMFwdDecl;
8828 if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) {
8829 struct_type->data.structure.llvm_full_type_queue_index = g->type_resolve_stack.length;
8830 g->type_resolve_stack.append(struct_type);
8831 return;
8832 } else {
8833 struct_type->data.structure.llvm_full_type_queue_index = SIZE_MAX;
8834 }
8835 }
8836
8837 size_t field_count = struct_type->data.structure.src_field_count;
8838 // Every field could potentially have a generated padding field after it.
8839 LLVMTypeRef *element_types = heap::c_allocator.allocate<LLVMTypeRef>(field_count * 2);
8840
8841 bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
8842 size_t packed_bits_offset = 0;
8843 size_t first_packed_bits_offset_misalign = SIZE_MAX;
8844 size_t debug_field_count = 0;
8845
8846 // trigger all the recursive get_llvm_type calls
8847 for (size_t i = 0; i < field_count; i += 1) {
8848 TypeStructField *field = struct_type->data.structure.fields[i];
8849 ZigType *field_type = field->type_entry;
8850 if (!type_has_bits(g, field_type))
8851 continue;
8852 (void)get_llvm_type(g, field_type);
8853 if (struct_type->data.structure.resolve_status >= wanted_resolve_status) return;
8854 }
8855
8856 size_t gen_field_index = 0;
8857
8858 // Calculate what LLVM thinks the ABI align of the struct will be. We do this to avoid
8859 // inserting padding bytes where LLVM would do it automatically.
8860 size_t llvm_struct_abi_align = 0;
8861 for (size_t i = 0; i < field_count; i += 1) {
8862 TypeStructField *field = struct_type->data.structure.fields[i];
8863 ZigType *field_type = field->type_entry;
8864 if (field->is_comptime || !type_has_bits(g, field_type))
8865 continue;
8866 LLVMTypeRef field_llvm_type = get_llvm_type(g, field_type);
8867 size_t llvm_field_abi_align = LLVMABIAlignmentOfType(g->target_data_ref, field_llvm_type);
8868 llvm_struct_abi_align = max(llvm_struct_abi_align, llvm_field_abi_align);
8869 }
8870
8871 ZigType* last_packed_field_type = nullptr;
8872
8873 for (size_t i = 0; i < field_count; i += 1) {
8874 TypeStructField *field = struct_type->data.structure.fields[i];
8875 ZigType *field_type = field->type_entry;
8876
8877 if (field->is_comptime || !type_has_bits(g, field_type)) {
8878 field->gen_index = SIZE_MAX;
8879 continue;
8880 }
8881
8882 if (packed) {
8883 last_packed_field_type = field_type;
8884 size_t field_size_in_bits = type_size_bits(g, field_type);
8885 size_t next_packed_bits_offset = packed_bits_offset + field_size_in_bits;
8886
8887 if (first_packed_bits_offset_misalign != SIZE_MAX) {
8888 // this field is not byte-aligned; it is part of the previous field with a bit offset
8889
8890 size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign;
8891 size_t full_abi_size = get_abi_size_bytes(full_bit_count, g->pointer_size_bytes);
8892 if (full_abi_size * 8 == full_bit_count) {
8893 // next field recovers ABI alignment
8894 element_types[gen_field_index] = get_llvm_type_of_n_bytes(full_abi_size);
8895 gen_field_index += 1;
8896 first_packed_bits_offset_misalign = SIZE_MAX;
8897 }
8898 } else if (get_abi_size_bytes(field_type->size_in_bits, g->pointer_size_bytes) * 8 != field_size_in_bits) {
8899 first_packed_bits_offset_misalign = packed_bits_offset;
8900 } else {
8901 // This is a byte-aligned field (both start and end) in a packed struct.
8902 element_types[gen_field_index] = get_llvm_type(g, field_type);
8903 assert(get_abi_size_bytes(field_type->size_in_bits, g->pointer_size_bytes) ==
8904 LLVMStoreSizeOfType(g->target_data_ref, element_types[gen_field_index]));
8905 gen_field_index += 1;
8906 }
8907 packed_bits_offset = next_packed_bits_offset;
8908 } else {
8909 LLVMTypeRef llvm_type;
8910 if (i == 0 && async_frame_type != nullptr) {
8911 assert(async_frame_type->id == ZigTypeIdFnFrame);
8912 assert(field_type->id == ZigTypeIdFn);
8913 resolve_llvm_types_fn(g, async_frame_type->data.frame.fn);
8914
8915 const unsigned addrspace = ZigLLVMDataLayoutGetProgramAddressSpace(g->target_data_ref);
8916 llvm_type = LLVMPointerType(async_frame_type->data.frame.fn->raw_type_ref, addrspace);
8917 } else {
8918 llvm_type = get_llvm_type(g, field_type);
8919 }
8920 element_types[gen_field_index] = llvm_type;
8921 field->gen_index = gen_field_index;
8922 gen_field_index += 1;
8923
8924 // find the next non-zero-byte field for offset calculations
8925 size_t next_src_field_index = i + 1;
8926 for (; next_src_field_index < field_count; next_src_field_index += 1) {
8927 if (type_has_bits(g, struct_type->data.structure.fields[next_src_field_index]->type_entry))
8928 break;
8929 }
8930 size_t next_abi_align;
8931 if (next_src_field_index == field_count) {
8932 next_abi_align = struct_type->abi_align;
8933 } else {
8934 if (struct_type->data.structure.fields[next_src_field_index]->align == 0) {
8935 next_abi_align = struct_type->data.structure.fields[next_src_field_index]->type_entry->abi_align;
8936 } else {
8937 next_abi_align = struct_type->data.structure.fields[next_src_field_index]->align;
8938 }
8939 }
8940 size_t llvm_next_abi_align = (next_src_field_index == field_count) ?
8941 llvm_struct_abi_align :
8942 LLVMABIAlignmentOfType(g->target_data_ref,
8943 get_llvm_type(g, struct_type->data.structure.fields[next_src_field_index]->type_entry));
8944
8945 size_t next_offset = next_field_offset(field->offset, struct_type->abi_align,
8946 field_type->abi_size, next_abi_align);
8947 size_t llvm_next_offset = next_field_offset(field->offset, llvm_struct_abi_align,
8948 LLVMABISizeOfType(g->target_data_ref, llvm_type), llvm_next_abi_align);
8949
8950 assert(next_offset >= llvm_next_offset);
8951 if (next_offset > llvm_next_offset) {
8952 size_t pad_bytes = next_offset - (field->offset + LLVMABISizeOfType(g->target_data_ref, llvm_type));
8953 if (pad_bytes != 0) {
8954 LLVMTypeRef pad_llvm_type = LLVMArrayType(LLVMInt8Type(), pad_bytes);
8955 element_types[gen_field_index] = pad_llvm_type;
8956 gen_field_index += 1;
8957 }
8958 }
8959 }
8960 debug_field_count += 1;
8961 }
8962 if (!packed) {
8963 struct_type->data.structure.gen_field_count = gen_field_index;
8964 }
8965
8966 if (first_packed_bits_offset_misalign != SIZE_MAX) {
8967 size_t full_bit_count = packed_bits_offset - first_packed_bits_offset_misalign;
8968 size_t full_abi_size = get_abi_size_bytes(full_bit_count, 1);
8969 if (last_packed_field_type->size_in_bits == full_bit_count && last_packed_field_type->id != ZigTypeIdInt && last_packed_field_type->id != ZigTypeIdEnum) {
8970 // If there is only one field that is misaligned and it is a custom type just use it
8971 element_types[gen_field_index] = get_llvm_type(g, last_packed_field_type);
8972 assert(full_abi_size == LLVMStoreSizeOfType(g->target_data_ref, element_types[gen_field_index]));
8973 } else {
8974 // Otherwise represent it as array of proper number of bytes in LLVM
8975 element_types[gen_field_index] = get_llvm_type_of_n_bytes(full_abi_size);
8976 }
8977 gen_field_index += 1;
8978 }
8979
8980 if (type_has_bits(g, struct_type)) {
8981 assert(struct_type->data.structure.gen_field_count == gen_field_index);
8982 LLVMStructSetBody(struct_type->llvm_type, element_types,
8983 (unsigned)struct_type->data.structure.gen_field_count, packed);
8984 }
8985
8986 ZigLLVMDIType **di_element_types = heap::c_allocator.allocate<ZigLLVMDIType*>(debug_field_count);
8987 size_t debug_field_index = 0;
8988 for (size_t i = 0; i < field_count; i += 1) {
8989 TypeStructField *field = struct_type->data.structure.fields[i];
8990 //fprintf(stderr, "%s at gen index %zu\n", buf_ptr(field->name), field->gen_index);
8991
8992 size_t gen_field_index = field->gen_index;
8993 if (gen_field_index == SIZE_MAX) {
8994 continue;
8995 }
8996
8997 ZigType *field_type = field->type_entry;
8998
8999 // if the field is a function, actually the debug info should be a pointer.
9000 ZigLLVMDIType *field_di_type;
9001 if (field_type->id == ZigTypeIdFn) {
9002 ZigType *field_ptr_type = get_pointer_to_type(g, field_type, true);
9003 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, get_llvm_type(g, field_ptr_type));
9004 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, get_llvm_type(g, field_ptr_type));
9005 field_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, get_llvm_di_type(g, field_type),
9006 debug_size_in_bits, debug_align_in_bits, buf_ptr(&field_ptr_type->name));
9007 } else {
9008 field_di_type = get_llvm_di_type(g, field_type);
9009 }
9010
9011 uint64_t debug_size_in_bits;
9012 uint64_t debug_align_in_bits;
9013 uint64_t debug_offset_in_bits;
9014 if (packed) {
9015 debug_size_in_bits = field->type_entry->size_in_bits;
9016 debug_align_in_bits = 8 * field->type_entry->abi_align;
9017 debug_offset_in_bits = 8 * field->offset + field->bit_offset_in_host;
9018 } else {
9019 debug_size_in_bits = 8 * get_store_size_bytes(field_type->size_in_bits);
9020 debug_align_in_bits = 8 * field_type->abi_align;
9021 debug_offset_in_bits = 8 * field->offset;
9022 }
9023 unsigned line;
9024 if (decl_node != nullptr) {
9025 AstNode *field_node = field->decl_node;
9026 line = node_line_onebased(field_node);
9027 } else {
9028 line = 0;
9029 }
9030 di_element_types[debug_field_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
9031 ZigLLVMTypeToScope(struct_type->llvm_di_type), buf_ptr(field->name),
9032 di_file, line,
9033 debug_size_in_bits,
9034 debug_align_in_bits,
9035 debug_offset_in_bits,
9036 ZigLLVM_DIFlags_Zero, field_di_type);
9037 assert(di_element_types[debug_field_index]);
9038 debug_field_index += 1;
9039 }
9040
9041 uint64_t debug_size_in_bits = 8*get_store_size_bytes(struct_type->size_in_bits);
9042 uint64_t debug_align_in_bits = 8*struct_type->abi_align;
9043 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
9044 di_scope,
9045 buf_ptr(&struct_type->name),
9046 di_file, line,
9047 debug_size_in_bits,
9048 debug_align_in_bits,
9049 ZigLLVM_DIFlags_Zero,
9050 nullptr, di_element_types, (int)debug_field_count, 0, nullptr, "");
9051
9052 ZigLLVMReplaceTemporary(g->dbuilder, struct_type->llvm_di_type, replacement_di_type);
9053 struct_type->llvm_di_type = replacement_di_type;
9054 struct_type->data.structure.resolve_status = ResolveStatusLLVMFull;
9055 if (struct_type->data.structure.llvm_full_type_queue_index != SIZE_MAX) {
9056 ZigType *last = g->type_resolve_stack.last();
9057 assert(last->id == ZigTypeIdStruct);
9058 last->data.structure.llvm_full_type_queue_index = struct_type->data.structure.llvm_full_type_queue_index;
9059 g->type_resolve_stack.swap_remove(struct_type->data.structure.llvm_full_type_queue_index);
9060 struct_type->data.structure.llvm_full_type_queue_index = SIZE_MAX;
9061 }
9062
9063 if (struct_type->abi_size <= 16 &&
9064 (struct_type->data.structure.layout == ContainerLayoutExtern ||
9065 struct_type->data.structure.layout == ContainerLayoutPacked))
9066 {
9067 resolve_llvm_c_abi_type(g, struct_type);
9068 }
9069}
9070
9071// This is to be used instead of void for debug info types, to avoid tripping
9072// Assertion `!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type"'
9073// when targeting CodeView (Windows).
9074static ZigLLVMDIType *make_empty_namespace_llvm_di_type(CodeGen *g, ZigType *import, const char *name,
9075 AstNode *decl_node)
9076{
9077 uint64_t debug_size_in_bits = 0;
9078 uint64_t debug_align_in_bits = 0;
9079 ZigLLVMDIType **di_element_types = nullptr;
9080 size_t debug_field_count = 0;
9081 return ZigLLVMCreateDebugStructType(g->dbuilder,
9082 ZigLLVMFileToScope(import->data.structure.root_struct->di_file),
9083 name,
9084 import->data.structure.root_struct->di_file, node_line_onebased(decl_node),
9085 debug_size_in_bits,
9086 debug_align_in_bits,
9087 ZigLLVM_DIFlags_Zero,
9088 nullptr, di_element_types, (int)debug_field_count, 0, nullptr, "");
9089}
9090
9091static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatus wanted_resolve_status) {
9092 assert(enum_type->data.enumeration.resolve_status >= ResolveStatusSizeKnown);
9093 if (enum_type->data.enumeration.resolve_status >= wanted_resolve_status) return;
9094
9095 Scope *scope = &enum_type->data.enumeration.decls_scope->base;
9096 ZigType *import = get_scope_import(scope);
9097 AstNode *decl_node = enum_type->data.enumeration.decl_node;
9098
9099 if (!type_has_bits(g, enum_type)) {
9100 enum_type->llvm_type = g->builtin_types.entry_void->llvm_type;
9101 enum_type->llvm_di_type = make_empty_namespace_llvm_di_type(g, import, buf_ptr(&enum_type->name),
9102 decl_node);
9103 enum_type->data.enumeration.resolve_status = ResolveStatusLLVMFull;
9104 return;
9105 }
9106
9107 uint32_t field_count = enum_type->data.enumeration.src_field_count;
9108
9109 assert(field_count == 0 || enum_type->data.enumeration.fields != nullptr);
9110 ZigLLVMDIEnumerator **di_enumerators = heap::c_allocator.allocate<ZigLLVMDIEnumerator*>(field_count);
9111
9112 for (uint32_t i = 0; i < field_count; i += 1) {
9113 TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i];
9114
9115 // https://github.com/ziglang/zig/issues/645
9116 di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(enum_field->name),
9117 bigint_as_signed(&enum_field->value), false);
9118 }
9119
9120 ZigType *tag_int_type = enum_type->data.enumeration.tag_int_type;
9121 enum_type->llvm_type = get_llvm_type(g, tag_int_type);
9122
9123 // create debug type for tag
9124 uint64_t tag_debug_size_in_bits = 8*tag_int_type->abi_size;
9125 uint64_t tag_debug_align_in_bits = 8*tag_int_type->abi_align;
9126 ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
9127 ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&enum_type->name),
9128 import->data.structure.root_struct->di_file, node_line_onebased(decl_node),
9129 tag_debug_size_in_bits,
9130 tag_debug_align_in_bits,
9131 di_enumerators, field_count,
9132 get_llvm_di_type(g, tag_int_type), "");
9133
9134 enum_type->llvm_di_type = tag_di_type;
9135 enum_type->data.enumeration.resolve_status = ResolveStatusLLVMFull;
9136}
9137
9138static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveStatus wanted_resolve_status) {
9139 if (union_type->data.unionation.resolve_status >= wanted_resolve_status) return;
9140
9141 bool packed = (union_type->data.unionation.layout == ContainerLayoutPacked);
9142 Scope *scope = &union_type->data.unionation.decls_scope->base;
9143 ZigType *import = get_scope_import(scope);
9144
9145 TypeUnionField *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;
9146 ZigType *tag_type = union_type->data.unionation.tag_type;
9147 uint32_t gen_field_count = union_type->data.unionation.gen_field_count;
9148 if (gen_field_count == 0) {
9149 if (tag_type == nullptr) {
9150 union_type->llvm_type = g->builtin_types.entry_void->llvm_type;
9151 union_type->llvm_di_type = make_empty_namespace_llvm_di_type(g, import, buf_ptr(&union_type->name),
9152 union_type->data.unionation.decl_node);
9153 } else {
9154 union_type->llvm_type = get_llvm_type(g, tag_type);
9155 union_type->llvm_di_type = get_llvm_di_type(g, tag_type);
9156 }
9157
9158 union_type->data.unionation.gen_union_index = SIZE_MAX;
9159 union_type->data.unionation.gen_tag_index = SIZE_MAX;
9160 union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;
9161 return;
9162 }
9163
9164 AstNode *decl_node = union_type->data.unionation.decl_node;
9165
9166 if (union_type->data.unionation.resolve_status < ResolveStatusLLVMFwdDecl) {
9167 union_type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&union_type->name));
9168 unsigned line = decl_node ? node_line_onebased(decl_node) : 0;
9169 unsigned dwarf_kind = ZigLLVMTag_DW_structure_type();
9170 union_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
9171 dwarf_kind, buf_ptr(&union_type->name),
9172 ZigLLVMFileToScope(import->data.structure.root_struct->di_file),
9173 import->data.structure.root_struct->di_file, line);
9174
9175 union_type->data.unionation.resolve_status = ResolveStatusLLVMFwdDecl;
9176 if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return;
9177 }
9178
9179 ZigLLVMDIType **union_inner_di_types = heap::c_allocator.allocate<ZigLLVMDIType*>(gen_field_count);
9180 uint32_t field_count = union_type->data.unionation.src_field_count;
9181 for (uint32_t i = 0; i < field_count; i += 1) {
9182 TypeUnionField *union_field = &union_type->data.unionation.fields[i];
9183 if (!type_has_bits(g, union_field->type_entry))
9184 continue;
9185
9186 ZigLLVMDIType *field_di_type = get_llvm_di_type(g, union_field->type_entry);
9187 if (union_type->data.unionation.resolve_status >= wanted_resolve_status) return;
9188
9189 uint64_t store_size_in_bits = union_field->type_entry->size_in_bits;
9190 uint64_t abi_align_in_bits = 8*union_field->type_entry->abi_align;
9191 AstNode *field_node = union_field->decl_node;
9192 union_inner_di_types[union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
9193 ZigLLVMTypeToScope(union_type->llvm_di_type), buf_ptr(union_field->enum_field->name),
9194 import->data.structure.root_struct->di_file, node_line_onebased(field_node),
9195 store_size_in_bits,
9196 abi_align_in_bits,
9197 0,
9198 ZigLLVM_DIFlags_Zero, field_di_type);
9199
9200 }
9201
9202 if (tag_type == nullptr || !type_has_bits(g, tag_type)) {
9203 assert(most_aligned_union_member != nullptr);
9204
9205 size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;
9206 if (padding_bytes > 0) {
9207 ZigType *u8_type = get_int_type(g, false, 8);
9208 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, nullptr);
9209 LLVMTypeRef union_element_types[] = {
9210 most_aligned_union_member->type_entry->llvm_type,
9211 get_llvm_type(g, padding_array),
9212 };
9213 LLVMStructSetBody(union_type->llvm_type, union_element_types, 2, packed);
9214 } else {
9215 LLVMStructSetBody(union_type->llvm_type, &most_aligned_union_member->type_entry->llvm_type, 1, packed);
9216 }
9217 union_type->data.unionation.union_llvm_type = union_type->llvm_type;
9218 union_type->data.unionation.gen_tag_index = SIZE_MAX;
9219 union_type->data.unionation.gen_union_index = SIZE_MAX;
9220
9221 // create debug type for union
9222 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,
9223 ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&union_type->name),
9224 import->data.structure.root_struct->di_file, node_line_onebased(decl_node),
9225 union_type->data.unionation.union_abi_size * 8,
9226 most_aligned_union_member->align * 8,
9227 ZigLLVM_DIFlags_Zero, union_inner_di_types,
9228 gen_field_count, 0, "");
9229
9230 ZigLLVMReplaceTemporary(g->dbuilder, union_type->llvm_di_type, replacement_di_type);
9231 union_type->llvm_di_type = replacement_di_type;
9232 union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;
9233 return;
9234 }
9235
9236 LLVMTypeRef union_type_ref;
9237 size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;
9238 if (padding_bytes == 0) {
9239 union_type_ref = get_llvm_type(g, most_aligned_union_member->type_entry);
9240 } else {
9241 ZigType *u8_type = get_int_type(g, false, 8);
9242 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, nullptr);
9243 LLVMTypeRef union_element_types[] = {
9244 get_llvm_type(g, most_aligned_union_member->type_entry),
9245 get_llvm_type(g, padding_array),
9246 };
9247 union_type_ref = LLVMStructType(union_element_types, 2, false);
9248 }
9249 union_type->data.unionation.union_llvm_type = union_type_ref;
9250
9251 LLVMTypeRef root_struct_element_types[2];
9252 root_struct_element_types[union_type->data.unionation.gen_tag_index] = get_llvm_type(g, tag_type);
9253 root_struct_element_types[union_type->data.unionation.gen_union_index] = union_type_ref;
9254 LLVMStructSetBody(union_type->llvm_type, root_struct_element_types, 2, packed);
9255
9256 // create debug type for union
9257 ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,
9258 ZigLLVMTypeToScope(union_type->llvm_di_type), "AnonUnion",
9259 import->data.structure.root_struct->di_file, node_line_onebased(decl_node),
9260 most_aligned_union_member->type_entry->size_in_bits, 8*most_aligned_union_member->align,
9261 ZigLLVM_DIFlags_Zero, union_inner_di_types, gen_field_count, 0, "");
9262
9263 uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, union_type->llvm_type,
9264 union_type->data.unionation.gen_union_index);
9265 uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, union_type->llvm_type,
9266 union_type->data.unionation.gen_tag_index);
9267
9268 ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,
9269 ZigLLVMTypeToScope(union_type->llvm_di_type), "payload",
9270 import->data.structure.root_struct->di_file, node_line_onebased(decl_node),
9271 most_aligned_union_member->type_entry->size_in_bits,
9272 8*most_aligned_union_member->align,
9273 union_offset_in_bits,
9274 ZigLLVM_DIFlags_Zero, union_di_type);
9275
9276 uint64_t tag_debug_size_in_bits = tag_type->size_in_bits;
9277 uint64_t tag_debug_align_in_bits = 8*tag_type->abi_align;
9278
9279 ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,
9280 ZigLLVMTypeToScope(union_type->llvm_di_type), "tag",
9281 import->data.structure.root_struct->di_file, node_line_onebased(decl_node),
9282 tag_debug_size_in_bits,
9283 tag_debug_align_in_bits,
9284 tag_offset_in_bits,
9285 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, tag_type));
9286
9287 ZigLLVMDIType *di_root_members[2];
9288 di_root_members[union_type->data.unionation.gen_tag_index] = tag_member_di_type;
9289 di_root_members[union_type->data.unionation.gen_union_index] = union_member_di_type;
9290
9291 uint64_t debug_size_in_bits = union_type->size_in_bits;
9292 uint64_t debug_align_in_bits = 8*union_type->abi_align;
9293 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
9294 ZigLLVMFileToScope(import->data.structure.root_struct->di_file),
9295 buf_ptr(&union_type->name),
9296 import->data.structure.root_struct->di_file, node_line_onebased(decl_node),
9297 debug_size_in_bits,
9298 debug_align_in_bits,
9299 ZigLLVM_DIFlags_Zero, nullptr, di_root_members, 2, 0, nullptr, "");
9300
9301 ZigLLVMReplaceTemporary(g->dbuilder, union_type->llvm_di_type, replacement_di_type);
9302 union_type->llvm_di_type = replacement_di_type;
9303 union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;
9304}
9305
9306static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
9307 if (type->llvm_di_type != nullptr) return;
9308
9309 if (resolve_pointer_zero_bits(g, type) != ErrorNone)
9310 zig_unreachable();
9311
9312 if (!type_has_bits(g, type)) {
9313 type->llvm_type = g->builtin_types.entry_void->llvm_type;
9314 type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type;
9315 return;
9316 }
9317
9318 ZigType *elem_type = type->data.pointer.child_type;
9319
9320 if (type->data.pointer.is_const || type->data.pointer.is_volatile ||
9321 type->data.pointer.explicit_alignment != 0 || type->data.pointer.ptr_len != PtrLenSingle ||
9322 type->data.pointer.bit_offset_in_host != 0 || type->data.pointer.allow_zero ||
9323 type->data.pointer.vector_index != VECTOR_INDEX_NONE || type->data.pointer.sentinel != nullptr)
9324 {
9325 assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl));
9326 ZigType *peer_type;
9327 if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) {
9328 peer_type = get_pointer_to_type_extra2(g, elem_type, false, false,
9329 PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false,
9330 VECTOR_INDEX_NONE, nullptr, nullptr);
9331 } else {
9332 uint32_t host_vec_len = type->data.pointer.host_int_bytes;
9333 ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type);
9334 peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false,
9335 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, nullptr);
9336 }
9337 type->llvm_type = get_llvm_type(g, peer_type);
9338 type->llvm_di_type = get_llvm_di_type(g, peer_type);
9339 assertNoError(type_resolve(g, elem_type, wanted_resolve_status));
9340 return;
9341 }
9342
9343 if (type->data.pointer.host_int_bytes == 0) {
9344 assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl));
9345 type->llvm_type = LLVMPointerType(elem_type->llvm_type, 0);
9346 uint64_t debug_size_in_bits = 8*get_store_size_bytes(type->size_in_bits);
9347 uint64_t debug_align_in_bits = 8*type->abi_align;
9348 type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, elem_type->llvm_di_type,
9349 debug_size_in_bits, debug_align_in_bits, buf_ptr(&type->name));
9350 assertNoError(type_resolve(g, elem_type, wanted_resolve_status));
9351 } else {
9352 ZigType *host_int_type = get_int_type(g, false, type->data.pointer.host_int_bytes * 8);
9353 LLVMTypeRef host_int_llvm_type = get_llvm_type(g, host_int_type);
9354 type->llvm_type = LLVMPointerType(host_int_llvm_type, 0);
9355 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, host_int_llvm_type);
9356 uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, host_int_llvm_type);
9357 type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, get_llvm_di_type(g, host_int_type),
9358 debug_size_in_bits, debug_align_in_bits, buf_ptr(&type->name));
9359 }
9360}
9361
9362static void resolve_llvm_types_integer(CodeGen *g, ZigType *type) {
9363 if (type->llvm_di_type != nullptr) return;
9364
9365 if (!type_has_bits(g, type)) {
9366 type->llvm_type = g->builtin_types.entry_void->llvm_type;
9367 type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type;
9368 return;
9369 }
9370
9371 unsigned dwarf_tag;
9372 if (type->data.integral.is_signed) {
9373 if (type->size_in_bits == 8) {
9374 dwarf_tag = ZigLLVMEncoding_DW_ATE_signed_char();
9375 } else {
9376 dwarf_tag = ZigLLVMEncoding_DW_ATE_signed();
9377 }
9378 } else {
9379 if (type->size_in_bits == 8) {
9380 dwarf_tag = ZigLLVMEncoding_DW_ATE_unsigned_char();
9381 } else {
9382 dwarf_tag = ZigLLVMEncoding_DW_ATE_unsigned();
9383 }
9384 }
9385
9386 type->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&type->name),
9387 type->size_in_bits, dwarf_tag);
9388 type->llvm_type = LLVMIntType(type->size_in_bits);
9389}
9390
9391static void resolve_llvm_types_optional(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
9392 assert(type->id == ZigTypeIdOptional);
9393 assert(type->data.maybe.resolve_status != ResolveStatusInvalid);
9394 assert(type->data.maybe.resolve_status >= ResolveStatusSizeKnown);
9395 if (type->data.maybe.resolve_status >= wanted_resolve_status) return;
9396
9397 LLVMTypeRef bool_llvm_type = get_llvm_type(g, g->builtin_types.entry_bool);
9398 ZigLLVMDIType *bool_llvm_di_type = get_llvm_di_type(g, g->builtin_types.entry_bool);
9399
9400 ZigType *child_type = type->data.maybe.child_type;
9401 if (!type_has_bits(g, child_type)) {
9402 type->llvm_type = bool_llvm_type;
9403 type->llvm_di_type = bool_llvm_di_type;
9404 type->data.maybe.resolve_status = ResolveStatusLLVMFull;
9405 return;
9406 }
9407
9408 if (type_is_nonnull_ptr(g, child_type) || child_type->id == ZigTypeIdErrorSet) {
9409 type->llvm_type = get_llvm_type(g, child_type);
9410 type->llvm_di_type = get_llvm_di_type(g, child_type);
9411 type->data.maybe.resolve_status = ResolveStatusLLVMFull;
9412 return;
9413 }
9414
9415 ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
9416 ZigLLVMDIFile *di_file = nullptr;
9417 unsigned line = 0;
9418
9419 if (type->data.maybe.resolve_status < ResolveStatusLLVMFwdDecl) {
9420 type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&type->name));
9421 unsigned dwarf_kind = ZigLLVMTag_DW_structure_type();
9422 type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
9423 dwarf_kind, buf_ptr(&type->name),
9424 compile_unit_scope, di_file, line);
9425
9426 type->data.maybe.resolve_status = ResolveStatusLLVMFwdDecl;
9427 if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return;
9428 }
9429
9430 ZigLLVMDIType *child_llvm_di_type = get_llvm_di_type(g, child_type);
9431 if (type->data.maybe.resolve_status >= wanted_resolve_status) return;
9432
9433 LLVMTypeRef elem_types[] = {
9434 get_llvm_type(g, child_type),
9435 LLVMInt1Type(),
9436 };
9437 LLVMStructSetBody(type->llvm_type, elem_types, 2, false);
9438
9439 uint64_t val_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type, maybe_child_index);
9440 uint64_t maybe_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type, maybe_null_index);
9441
9442 ZigLLVMDIType *di_element_types[2];
9443 di_element_types[maybe_child_index] =
9444 ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type),
9445 "val", di_file, line,
9446 8 * child_type->abi_size,
9447 8 * child_type->abi_align,
9448 val_offset_in_bits,
9449 ZigLLVM_DIFlags_Zero, child_llvm_di_type);
9450 di_element_types[maybe_null_index] =
9451 ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type),
9452 "maybe", di_file, line,
9453 8*g->builtin_types.entry_bool->abi_size,
9454 8*g->builtin_types.entry_bool->abi_align,
9455 maybe_offset_in_bits,
9456 ZigLLVM_DIFlags_Zero, bool_llvm_di_type);
9457 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
9458 compile_unit_scope,
9459 buf_ptr(&type->name),
9460 di_file, line, 8 * type->abi_size, 8 * type->abi_align, ZigLLVM_DIFlags_Zero,
9461 nullptr, di_element_types, 2, 0, nullptr, "");
9462
9463 ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type);
9464 type->llvm_di_type = replacement_di_type;
9465 type->data.maybe.resolve_status = ResolveStatusLLVMFull;
9466}
9467
9468static void resolve_llvm_types_error_union(CodeGen *g, ZigType *type) {
9469 if (type->llvm_di_type != nullptr) return;
9470
9471 ZigType *payload_type = type->data.error_union.payload_type;
9472 ZigType *err_set_type = type->data.error_union.err_set_type;
9473
9474 if (!type_has_bits(g, payload_type)) {
9475 assert(type_has_bits(g, err_set_type));
9476 type->llvm_type = get_llvm_type(g, err_set_type);
9477 type->llvm_di_type = get_llvm_di_type(g, err_set_type);
9478 } else if (!type_has_bits(g, err_set_type)) {
9479 type->llvm_type = get_llvm_type(g, payload_type);
9480 type->llvm_di_type = get_llvm_di_type(g, payload_type);
9481 } else {
9482 LLVMTypeRef err_set_llvm_type = get_llvm_type(g, err_set_type);
9483 LLVMTypeRef payload_llvm_type = get_llvm_type(g, payload_type);
9484 LLVMTypeRef elem_types[3];
9485 elem_types[err_union_err_index] = err_set_llvm_type;
9486 elem_types[err_union_payload_index] = payload_llvm_type;
9487
9488 type->llvm_type = LLVMStructType(elem_types, 2, false);
9489 if (LLVMABISizeOfType(g->target_data_ref, type->llvm_type) != type->abi_size) {
9490 // we need to do our own padding
9491 type->data.error_union.pad_llvm_type = LLVMArrayType(LLVMInt8Type(), type->data.error_union.pad_bytes);
9492 elem_types[2] = type->data.error_union.pad_llvm_type;
9493 type->llvm_type = LLVMStructType(elem_types, 3, false);
9494 }
9495
9496 ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
9497 ZigLLVMDIFile *di_file = nullptr;
9498 unsigned line = 0;
9499 type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
9500 ZigLLVMTag_DW_structure_type(), buf_ptr(&type->name),
9501 compile_unit_scope, di_file, line);
9502
9503 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, err_set_llvm_type);
9504 uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, err_set_llvm_type);
9505 uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type, err_union_err_index);
9506
9507 uint64_t value_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, payload_llvm_type);
9508 uint64_t value_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, payload_llvm_type);
9509 uint64_t value_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type,
9510 err_union_payload_index);
9511
9512 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, type->llvm_type);
9513 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, type->llvm_type);
9514
9515 ZigLLVMDIType *di_element_types[2];
9516 di_element_types[err_union_err_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
9517 ZigLLVMTypeToScope(type->llvm_di_type),
9518 "tag", di_file, line,
9519 tag_debug_size_in_bits,
9520 tag_debug_align_in_bits,
9521 tag_offset_in_bits,
9522 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, err_set_type));
9523 di_element_types[err_union_payload_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
9524 ZigLLVMTypeToScope(type->llvm_di_type),
9525 "value", di_file, line,
9526 value_debug_size_in_bits,
9527 value_debug_align_in_bits,
9528 value_offset_in_bits,
9529 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, payload_type));
9530
9531 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
9532 compile_unit_scope,
9533 buf_ptr(&type->name),
9534 di_file, line,
9535 debug_size_in_bits,
9536 debug_align_in_bits,
9537 ZigLLVM_DIFlags_Zero,
9538 nullptr, di_element_types, 2, 0, nullptr, "");
9539
9540 ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type);
9541 type->llvm_di_type = replacement_di_type;
9542 }
9543}
9544
9545static void resolve_llvm_types_array(CodeGen *g, ZigType *type) {
9546 if (type->llvm_di_type != nullptr) return;
9547
9548 if (!type_has_bits(g, type)) {
9549 type->llvm_type = g->builtin_types.entry_void->llvm_type;
9550 type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type;
9551 return;
9552 }
9553
9554 ZigType *elem_type = type->data.array.child_type;
9555
9556 uint64_t extra_len_from_sentinel = (type->data.array.sentinel != nullptr) ? 1 : 0;
9557 uint64_t full_len = type->data.array.len + extra_len_from_sentinel;
9558 // TODO https://github.com/ziglang/zig/issues/1424
9559 type->llvm_type = LLVMArrayType(get_llvm_type(g, elem_type), (unsigned)full_len);
9560
9561 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, type->llvm_type);
9562 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, type->llvm_type);
9563
9564 type->llvm_di_type = ZigLLVMCreateDebugArrayType(g->dbuilder, debug_size_in_bits,
9565 debug_align_in_bits, get_llvm_di_type(g, elem_type), (int)full_len);
9566}
9567
9568static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {
9569 if (fn_type->llvm_di_type != nullptr) return;
9570
9571 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
9572 bool first_arg_return = want_first_arg_sret(g, fn_type_id);
9573 bool is_async = fn_type_id->cc == CallingConventionAsync;
9574 bool is_c_abi = !calling_convention_allows_zig_types(fn_type_id->cc);
9575 bool prefix_arg_error_return_trace = g->have_err_ret_tracing && fn_type_can_fail(fn_type_id);
9576 // +1 for maybe making the first argument the return value
9577 // +1 for maybe first argument the error return trace
9578 // +2 for maybe arguments async allocator and error code pointer
9579 ZigList<LLVMTypeRef> gen_param_types = {};
9580 // +1 because 0 is the return type and
9581 // +1 for maybe making first arg ret val and
9582 // +1 for maybe first argument the error return trace
9583 // +2 for maybe arguments async allocator and error code pointer
9584 ZigList<ZigLLVMDIType *> param_di_types = {};
9585 ZigType *gen_return_type;
9586 if (is_async) {
9587 gen_return_type = g->builtin_types.entry_void;
9588 param_di_types.append(nullptr);
9589 } else if (!type_has_bits(g, fn_type_id->return_type)) {
9590 gen_return_type = g->builtin_types.entry_void;
9591 param_di_types.append(nullptr);
9592 } else if (first_arg_return) {
9593 gen_return_type = g->builtin_types.entry_void;
9594 param_di_types.append(nullptr);
9595 ZigType *gen_type = get_pointer_to_type(g, fn_type_id->return_type, false);
9596 gen_param_types.append(get_llvm_type(g, gen_type));
9597 param_di_types.append(get_llvm_di_type(g, gen_type));
9598 } else {
9599 gen_return_type = fn_type_id->return_type;
9600 param_di_types.append(get_llvm_di_type(g, gen_return_type));
9601 }
9602 fn_type->data.fn.gen_return_type = gen_return_type;
9603
9604 if (prefix_arg_error_return_trace && !is_async) {
9605 ZigType *gen_type = get_pointer_to_type(g, get_stack_trace_type(g), false);
9606 gen_param_types.append(get_llvm_type(g, gen_type));
9607 param_di_types.append(get_llvm_di_type(g, gen_type));
9608 }
9609 if (is_async) {
9610 fn_type->data.fn.gen_param_info = heap::c_allocator.allocate<FnGenParamInfo>(2);
9611
9612 ZigType *frame_type = get_any_frame_type(g, fn_type_id->return_type);
9613 gen_param_types.append(get_llvm_type(g, frame_type));
9614 param_di_types.append(get_llvm_di_type(g, frame_type));
9615
9616 fn_type->data.fn.gen_param_info[0].src_index = 0;
9617 fn_type->data.fn.gen_param_info[0].gen_index = 0;
9618 fn_type->data.fn.gen_param_info[0].type = frame_type;
9619
9620 gen_param_types.append(get_llvm_type(g, g->builtin_types.entry_usize));
9621 param_di_types.append(get_llvm_di_type(g, g->builtin_types.entry_usize));
9622
9623 fn_type->data.fn.gen_param_info[1].src_index = 1;
9624 fn_type->data.fn.gen_param_info[1].gen_index = 1;
9625 fn_type->data.fn.gen_param_info[1].type = g->builtin_types.entry_usize;
9626 } else {
9627 fn_type->data.fn.gen_param_info = heap::c_allocator.allocate<FnGenParamInfo>(fn_type_id->param_count);
9628 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
9629 FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i];
9630 ZigType *type_entry = src_param_info->type;
9631 FnGenParamInfo *gen_param_info = &fn_type->data.fn.gen_param_info[i];
9632
9633 gen_param_info->src_index = i;
9634 gen_param_info->gen_index = SIZE_MAX;
9635
9636 if (is_c_abi || !type_has_bits(g, type_entry))
9637 continue;
9638
9639 ZigType *gen_type;
9640 if (handle_is_ptr(g, type_entry)) {
9641 gen_type = get_pointer_to_type(g, type_entry, true);
9642 gen_param_info->is_byval = true;
9643 } else {
9644 gen_type = type_entry;
9645 }
9646 gen_param_info->gen_index = gen_param_types.length;
9647 gen_param_info->type = gen_type;
9648 gen_param_types.append(get_llvm_type(g, gen_type));
9649
9650 param_di_types.append(get_llvm_di_type(g, gen_type));
9651 }
9652 }
9653
9654 if (is_c_abi) {
9655 FnWalk fn_walk = {};
9656 fn_walk.id = FnWalkIdTypes;
9657 fn_walk.data.types.param_di_types = &param_di_types;
9658 fn_walk.data.types.gen_param_types = &gen_param_types;
9659 walk_function_params(g, fn_type, &fn_walk);
9660 }
9661
9662 fn_type->data.fn.gen_param_count = gen_param_types.length;
9663
9664 for (size_t i = 0; i < gen_param_types.length; i += 1) {
9665 assert(gen_param_types.items[i] != nullptr);
9666 }
9667
9668 if (!first_arg_return && fn_returns_c_abi_small_struct(fn_type_id)) {
9669 fn_type->data.fn.raw_type_ref = LLVMFunctionType(get_llvm_c_abi_type(g, gen_return_type),
9670 gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);
9671 } else {
9672 fn_type->data.fn.raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type),
9673 gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);
9674 }
9675 const unsigned fn_addrspace = ZigLLVMDataLayoutGetProgramAddressSpace(g->target_data_ref);
9676 fn_type->llvm_type = LLVMPointerType(fn_type->data.fn.raw_type_ref, fn_addrspace);
9677 fn_type->data.fn.raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);
9678 fn_type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, fn_type->data.fn.raw_di_type,
9679 LLVMStoreSizeOfType(g->target_data_ref, fn_type->llvm_type),
9680 LLVMABIAlignmentOfType(g->target_data_ref, fn_type->llvm_type), "");
9681
9682 gen_param_types.deinit();
9683 param_di_types.deinit();
9684}
9685
9686void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) {
9687 Error err;
9688 if (fn->raw_di_type != nullptr) return;
9689
9690 ZigType *fn_type = fn->type_entry;
9691 if (!fn_is_async(fn)) {
9692 resolve_llvm_types_fn_type(g, fn_type);
9693 fn->raw_type_ref = fn_type->data.fn.raw_type_ref;
9694 fn->raw_di_type = fn_type->data.fn.raw_di_type;
9695 return;
9696 }
9697
9698 ZigType *gen_return_type = g->builtin_types.entry_void;
9699 ZigList<ZigLLVMDIType *> param_di_types = {};
9700 ZigList<LLVMTypeRef> gen_param_types = {};
9701 // first "parameter" is return value
9702 param_di_types.append(nullptr);
9703
9704 ZigType *frame_type = get_fn_frame_type(g, fn);
9705 ZigType *ptr_type = get_pointer_to_type(g, frame_type, false);
9706 if ((err = type_resolve(g, ptr_type, ResolveStatusLLVMFwdDecl)))
9707 zig_unreachable();
9708 gen_param_types.append(ptr_type->llvm_type);
9709 param_di_types.append(ptr_type->llvm_di_type);
9710
9711 // this parameter is used to pass the result pointer when await completes
9712 gen_param_types.append(get_llvm_type(g, g->builtin_types.entry_usize));
9713 param_di_types.append(get_llvm_di_type(g, g->builtin_types.entry_usize));
9714
9715 fn->raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type),
9716 gen_param_types.items, gen_param_types.length, false);
9717 fn->raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);
9718
9719 param_di_types.deinit();
9720 gen_param_types.deinit();
9721}
9722
9723static void resolve_llvm_types_anyerror(CodeGen *g) {
9724 ZigType *entry = g->builtin_types.entry_global_error_set;
9725 entry->llvm_type = get_llvm_type(g, g->err_tag_type);
9726 ZigList<ZigLLVMDIEnumerator *> err_enumerators = {};
9727 // reserve index 0 to indicate no error
9728 err_enumerators.append(ZigLLVMCreateDebugEnumerator(g->dbuilder, "(none)", 0, false));
9729 for (size_t i = 1; i < g->errors_by_index.length; i += 1) {
9730 ErrorTableEntry *error_entry = g->errors_by_index.at(i);
9731 err_enumerators.append(ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(&error_entry->name), i, false));
9732 }
9733
9734 // create debug type for error sets
9735 uint64_t tag_debug_size_in_bits = g->err_tag_type->size_in_bits;
9736 uint64_t tag_debug_align_in_bits = 8*g->err_tag_type->abi_align;
9737 ZigLLVMDIFile *err_set_di_file = nullptr;
9738 entry->llvm_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
9739 ZigLLVMCompileUnitToScope(g->compile_unit), buf_ptr(&entry->name),
9740 err_set_di_file, 0,
9741 tag_debug_size_in_bits,
9742 tag_debug_align_in_bits,
9743 err_enumerators.items, err_enumerators.length,
9744 get_llvm_di_type(g, g->err_tag_type), "");
9745
9746 err_enumerators.deinit();
9747}
9748
9749static void resolve_llvm_types_async_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) {
9750 Error err;
9751 if ((err = type_resolve(g, frame_type, ResolveStatusSizeKnown)))
9752 zig_unreachable();
9753
9754 ZigType *passed_frame_type = fn_is_async(frame_type->data.frame.fn) ? frame_type : nullptr;
9755 resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status, passed_frame_type);
9756 frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type;
9757 frame_type->llvm_di_type = frame_type->data.frame.locals_struct->llvm_di_type;
9758}
9759
9760static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, ResolveStatus wanted_resolve_status) {
9761 if (any_frame_type->llvm_di_type != nullptr) return;
9762
9763 Buf *name = buf_sprintf("(%s header)", buf_ptr(&any_frame_type->name));
9764 LLVMTypeRef frame_header_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(name));
9765 any_frame_type->llvm_type = LLVMPointerType(frame_header_type, 0);
9766 any_frame_type->data.any_frame.struct_llvm_ty = frame_header_type;
9767
9768 unsigned dwarf_kind = ZigLLVMTag_DW_structure_type();
9769 ZigLLVMDIFile *di_file = nullptr;
9770 ZigLLVMDIScope *di_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
9771 unsigned line = 0;
9772 ZigLLVMDIType *frame_header_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
9773 dwarf_kind, buf_ptr(name), di_scope, di_file, line);
9774 any_frame_type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, frame_header_di_type,
9775 8*g->pointer_size_bytes, 8*g->builtin_types.entry_usize->abi_align, buf_ptr(&any_frame_type->name));
9776
9777 LLVMTypeRef llvm_void = LLVMVoidType();
9778 LLVMTypeRef arg_types[] = {any_frame_type->llvm_type, g->builtin_types.entry_usize->llvm_type};
9779 LLVMTypeRef fn_type = LLVMFunctionType(llvm_void, arg_types, 2, false);
9780 LLVMTypeRef usize_type_ref = get_llvm_type(g, g->builtin_types.entry_usize);
9781 ZigLLVMDIType *usize_di_type = get_llvm_di_type(g, g->builtin_types.entry_usize);
9782 ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
9783
9784 ZigType *result_type = any_frame_type->data.any_frame.result_type;
9785 ZigType *ptr_result_type = (result_type == nullptr) ? nullptr : get_pointer_to_type(g, result_type, false);
9786 const unsigned fn_addrspace = ZigLLVMDataLayoutGetProgramAddressSpace(g->target_data_ref);
9787 LLVMTypeRef ptr_fn_llvm_type = LLVMPointerType(fn_type, fn_addrspace);
9788 if (result_type == nullptr) {
9789 g->any_frame_header_llvm_ty = frame_header_type;
9790 g->anyframe_fn_type = fn_type;
9791 }
9792
9793 ZigList<LLVMTypeRef> field_types = {};
9794 ZigList<ZigLLVMDIType *> di_element_types = {};
9795
9796 // label (grep this): [fn_frame_struct_layout]
9797 field_types.append(ptr_fn_llvm_type); // fn_ptr
9798 field_types.append(usize_type_ref); // resume_index
9799 field_types.append(usize_type_ref); // awaiter
9800
9801 bool have_result_type = result_type != nullptr && type_has_bits(g, result_type);
9802 if (have_result_type) {
9803 field_types.append(get_llvm_type(g, ptr_result_type)); // result_ptr_callee
9804 field_types.append(get_llvm_type(g, ptr_result_type)); // result_ptr_awaiter
9805 field_types.append(get_llvm_type(g, result_type)); // result
9806 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {
9807 ZigType *ptr_stack_trace = get_pointer_to_type(g, get_stack_trace_type(g), false);
9808 field_types.append(get_llvm_type(g, ptr_stack_trace)); // ptr_stack_trace_callee
9809 field_types.append(get_llvm_type(g, ptr_stack_trace)); // ptr_stack_trace_awaiter
9810 }
9811 }
9812 LLVMStructSetBody(frame_header_type, field_types.items, field_types.length, false);
9813
9814 di_element_types.append(
9815 ZigLLVMCreateDebugMemberType(g->dbuilder,
9816 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "fn_ptr",
9817 di_file, line,
9818 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9819 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9820 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),
9821 ZigLLVM_DIFlags_Zero, usize_di_type));
9822 di_element_types.append(
9823 ZigLLVMCreateDebugMemberType(g->dbuilder,
9824 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "resume_index",
9825 di_file, line,
9826 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9827 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9828 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),
9829 ZigLLVM_DIFlags_Zero, usize_di_type));
9830 di_element_types.append(
9831 ZigLLVMCreateDebugMemberType(g->dbuilder,
9832 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "awaiter",
9833 di_file, line,
9834 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9835 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9836 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),
9837 ZigLLVM_DIFlags_Zero, usize_di_type));
9838
9839 if (have_result_type) {
9840 di_element_types.append(
9841 ZigLLVMCreateDebugMemberType(g->dbuilder,
9842 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "result_ptr_callee",
9843 di_file, line,
9844 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9845 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9846 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),
9847 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_result_type)));
9848 di_element_types.append(
9849 ZigLLVMCreateDebugMemberType(g->dbuilder,
9850 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "result_ptr_awaiter",
9851 di_file, line,
9852 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9853 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9854 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),
9855 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_result_type)));
9856 di_element_types.append(
9857 ZigLLVMCreateDebugMemberType(g->dbuilder,
9858 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "result",
9859 di_file, line,
9860 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9861 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9862 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),
9863 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, result_type)));
9864
9865 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {
9866 ZigType *ptr_stack_trace = get_pointer_to_type(g, get_stack_trace_type(g), false);
9867 di_element_types.append(
9868 ZigLLVMCreateDebugMemberType(g->dbuilder,
9869 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "ptr_stack_trace_callee",
9870 di_file, line,
9871 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9872 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9873 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),
9874 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_stack_trace)));
9875 di_element_types.append(
9876 ZigLLVMCreateDebugMemberType(g->dbuilder,
9877 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "ptr_stack_trace_awaiter",
9878 di_file, line,
9879 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9880 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
9881 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),
9882 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_stack_trace)));
9883 }
9884 };
9885
9886 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
9887 compile_unit_scope, buf_ptr(name),
9888 di_file, line,
9889 8*LLVMABISizeOfType(g->target_data_ref, frame_header_type),
9890 8*LLVMABIAlignmentOfType(g->target_data_ref, frame_header_type),
9891 ZigLLVM_DIFlags_Zero,
9892 nullptr, di_element_types.items, di_element_types.length, 0, nullptr, "");
9893
9894 ZigLLVMReplaceTemporary(g->dbuilder, frame_header_di_type, replacement_di_type);
9895
9896 field_types.deinit();
9897 di_element_types.deinit();
9898}
9899
9900static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
9901 assert(wanted_resolve_status > ResolveStatusSizeKnown);
9902 switch (type->id) {
9903 case ZigTypeIdInvalid:
9904 case ZigTypeIdMetaType:
9905 case ZigTypeIdComptimeFloat:
9906 case ZigTypeIdComptimeInt:
9907 case ZigTypeIdEnumLiteral:
9908 case ZigTypeIdUndefined:
9909 case ZigTypeIdNull:
9910 case ZigTypeIdBoundFn:
9911 zig_unreachable();
9912 case ZigTypeIdFloat:
9913 case ZigTypeIdOpaque:
9914 case ZigTypeIdVoid:
9915 case ZigTypeIdBool:
9916 case ZigTypeIdUnreachable:
9917 assert(type->llvm_di_type != nullptr);
9918 return;
9919 case ZigTypeIdStruct:
9920 if (type->data.structure.special == StructSpecialSlice)
9921 return resolve_llvm_types_slice(g, type, wanted_resolve_status);
9922 else
9923 return resolve_llvm_types_struct(g, type, wanted_resolve_status, nullptr);
9924 case ZigTypeIdEnum:
9925 return resolve_llvm_types_enum(g, type, wanted_resolve_status);
9926 case ZigTypeIdUnion:
9927 return resolve_llvm_types_union(g, type, wanted_resolve_status);
9928 case ZigTypeIdPointer:
9929 return resolve_llvm_types_pointer(g, type, wanted_resolve_status);
9930 case ZigTypeIdInt:
9931 return resolve_llvm_types_integer(g, type);
9932 case ZigTypeIdOptional:
9933 return resolve_llvm_types_optional(g, type, wanted_resolve_status);
9934 case ZigTypeIdErrorUnion:
9935 return resolve_llvm_types_error_union(g, type);
9936 case ZigTypeIdArray:
9937 return resolve_llvm_types_array(g, type);
9938 case ZigTypeIdFn:
9939 return resolve_llvm_types_fn_type(g, type);
9940 case ZigTypeIdErrorSet: {
9941 if (type->llvm_di_type != nullptr) return;
9942
9943 if (g->builtin_types.entry_global_error_set->llvm_type == nullptr) {
9944 resolve_llvm_types_anyerror(g);
9945 }
9946 type->llvm_type = g->builtin_types.entry_global_error_set->llvm_type;
9947 type->llvm_di_type = g->builtin_types.entry_global_error_set->llvm_di_type;
9948 return;
9949 }
9950 case ZigTypeIdVector: {
9951 if (type->llvm_di_type != nullptr) return;
9952
9953 type->llvm_type = LLVMVectorType(get_llvm_type(g, type->data.vector.elem_type),
9954 type->data.vector.len);
9955
9956 type->llvm_di_type = ZigLLVMDIBuilderCreateVectorType(g->dbuilder,
9957 8 * type->abi_size,
9958 8 * type->abi_align,
9959 get_llvm_di_type(g, type->data.vector.elem_type),
9960 type->data.vector.len);
9961 return;
9962 }
9963 case ZigTypeIdFnFrame:
9964 return resolve_llvm_types_async_frame(g, type, wanted_resolve_status);
9965 case ZigTypeIdAnyFrame:
9966 return resolve_llvm_types_any_frame(g, type, wanted_resolve_status);
9967 }
9968 zig_unreachable();
9969}
9970
9971LLVMTypeRef get_llvm_c_abi_type(CodeGen *g, ZigType *type) {
9972 assertNoError(type_resolve(g, type, ResolveStatusLLVMFull));
9973 assert(type->abi_size == 0 || type->abi_size >= LLVMABISizeOfType(g->target_data_ref, type->llvm_type));
9974 assert(type->abi_align == 0 || type->abi_align >= LLVMABIAlignmentOfType(g->target_data_ref, type->llvm_type));
9975 return type->llvm_c_abi_type;
9976}
9977
9978LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type) {
9979 assertNoError(type_resolve(g, type, ResolveStatusLLVMFull));
9980 assert(type->abi_size == 0 || type->abi_size >= LLVMABISizeOfType(g->target_data_ref, type->llvm_type));
9981 assert(type->abi_align == 0 || type->abi_align >= LLVMABIAlignmentOfType(g->target_data_ref, type->llvm_type));
9982 return type->llvm_type;
9983}
9984
9985ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type) {
9986 assertNoError(type_resolve(g, type, ResolveStatusLLVMFull));
9987 return type->llvm_di_type;
9988}
9989
9990void src_assert_impl(bool ok, AstNode *source_node, char const *file, unsigned int line) {
9991 if (ok) return;
9992 if (source_node == nullptr) {
9993 fprintf(stderr, "when analyzing (unknown source location) ");
9994 } else {
9995 RootStruct *root_struct = source_node->owner->data.structure.root_struct;
9996 fprintf(stderr, "when analyzing %s:%u:%u ", buf_ptr(root_struct->path),
9997 node_line_onebased(source_node), node_column_onebased(source_node));
9998 }
9999 fprintf(stderr, "in compiler source at %s:%u: ", file, line);
10000 const char *msg = "assertion failed. This is a bug in the Zig compiler.";
10001 stage2_panic(msg, strlen(msg));
10002}
10003
10004Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
10005 ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path)
10006{
10007 Error err;
10008
10009 Buf *search_dir;
10010 ZigPackage *cur_scope_pkg = source_import->data.structure.root_struct->package;
10011 assert(cur_scope_pkg);
10012 ZigPackage *target_package;
10013 auto package_entry = cur_scope_pkg->package_table.maybe_get(import_target_str);
10014 SourceKind source_kind;
10015 if (package_entry) {
10016 target_package = package_entry->value;
10017 *out_import_target_path = &target_package->root_src_path;
10018 search_dir = &target_package->root_src_dir;
10019 source_kind = SourceKindPkgMain;
10020 } else {
10021 // try it as a filename
10022 target_package = cur_scope_pkg;
10023 *out_import_target_path = import_target_str;
10024
10025 // search relative to importing file
10026 search_dir = buf_alloc();
10027 os_path_dirname(source_import->data.structure.root_struct->path, search_dir);
10028
10029 source_kind = SourceKindNonRoot;
10030 }
10031
10032 buf_resize(out_full_path, 0);
10033 os_path_join(search_dir, *out_import_target_path, out_full_path);
10034
10035 Buf *import_code = buf_alloc();
10036 Buf *resolved_path = buf_alloc();
10037
10038 Buf *resolve_paths[] = { out_full_path, };
10039 *resolved_path = os_path_resolve(resolve_paths, 1);
10040
10041 auto import_entry = g->import_table.maybe_get(resolved_path);
10042 if (import_entry) {
10043 *out_import = import_entry->value;
10044 return ErrorNone;
10045 }
10046
10047 if (source_kind == SourceKindNonRoot) {
10048 Buf *pkg_root_src_dir = &cur_scope_pkg->root_src_dir;
10049 Buf resolved_root_src_dir = os_path_resolve(&pkg_root_src_dir, 1);
10050 if (!buf_starts_with_buf(resolved_path, &resolved_root_src_dir)) {
10051 return ErrorImportOutsidePkgPath;
10052 }
10053 }
10054
10055 if ((err = file_fetch(g, resolved_path, import_code))) {
10056 return err;
10057 }
10058
10059 *out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind);
10060 return ErrorNone;
10061}
10062
10063void AstNode::src() {
10064 RootStruct *root_struct = this->owner->data.structure.root_struct;
10065 uint32_t line = root_struct->token_locs[this->main_token].line + 1;
10066 uint32_t column = root_struct->token_locs[this->main_token].column + 1;
10067 fprintf(stderr, "%s:%" PRIu32 ":%" PRIu32 "\n",
10068 buf_ptr(root_struct->path),
10069 line, column);
10070}
10071
10072void Stage1Air::src() {
10073 Stage1Air *it;
10074 for (it = this; it != nullptr && it->source_node != nullptr; it = it->parent_exec) {
10075 it->source_node->src();
10076 }
10077}
10078
10079bool is_anon_container(ZigType *ty) {
10080 return ty->id == ZigTypeIdStruct && (
10081 ty->data.structure.special == StructSpecialInferredTuple ||
10082 ty->data.structure.special == StructSpecialInferredStruct);
10083}
10084
10085bool is_opt_err_set(ZigType *ty) {
10086 return ty->id == ZigTypeIdErrorSet ||
10087 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
10088}
10089
10090// Returns whether the x_optional field of ZigValue is active.
10091bool type_has_optional_repr(ZigType *ty) {
10092 if (ty->id != ZigTypeIdOptional) {
10093 return false;
10094 } else if (get_src_ptr_type(ty) != nullptr) {
10095 return false;
10096 } else if (is_opt_err_set(ty)) {
10097 return false;
10098 } else {
10099 return true;
10100 }
10101}
10102
10103void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) {
10104 uint32_t prev_align = dest->llvm_align;
10105 ConstParent prev_parent = dest->parent;
10106 memcpy(dest, src, sizeof(ZigValue));
10107 dest->llvm_align = prev_align;
10108 if (src->special != ConstValSpecialStatic)
10109 return;
10110 dest->parent = prev_parent;
10111 if (dest->type->id == ZigTypeIdStruct) {
10112 dest->data.x_struct.fields = alloc_const_vals_ptrs(g, dest->type->data.structure.src_field_count);
10113 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
10114 TypeStructField *type_struct_field = dest->type->data.structure.fields[i];
10115 if (type_struct_field->is_comptime) {
10116 // comptime-known values are stored in the field init_val inside
10117 // the struct type. The data stored here is not supposed to be read
10118 // at all; the code should look at the type system and notice the field
10119 // is comptime and look at the type to learn the value.
10120 continue;
10121 }
10122 copy_const_val(g, dest->data.x_struct.fields[i], src->data.x_struct.fields[i]);
10123 dest->data.x_struct.fields[i]->parent.id = ConstParentIdStruct;
10124 dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;
10125 dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i;
10126 }
10127 } else if (dest->type->id == ZigTypeIdArray) {
10128 switch (dest->data.x_array.special) {
10129 case ConstArraySpecialNone: {
10130 dest->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(dest->type->data.array.len);
10131 for (uint64_t i = 0; i < dest->type->data.array.len; i += 1) {
10132 copy_const_val(g, &dest->data.x_array.data.s_none.elements[i], &src->data.x_array.data.s_none.elements[i]);
10133 dest->data.x_array.data.s_none.elements[i].parent.id = ConstParentIdArray;
10134 dest->data.x_array.data.s_none.elements[i].parent.data.p_array.array_val = dest;
10135 dest->data.x_array.data.s_none.elements[i].parent.data.p_array.elem_index = i;
10136 }
10137 break;
10138 }
10139 case ConstArraySpecialUndef: {
10140 // Nothing to copy; the above memcpy did everything we needed.
10141 break;
10142 }
10143 case ConstArraySpecialBuf: {
10144 dest->data.x_array.data.s_buf = buf_create_from_buf(src->data.x_array.data.s_buf);
10145 break;
10146 }
10147 }
10148 } else if (dest->type->id == ZigTypeIdUnion) {
10149 bigint_init_bigint(&dest->data.x_union.tag, &src->data.x_union.tag);
10150 dest->data.x_union.payload = g->pass1_arena->create<ZigValue>();
10151 copy_const_val(g, dest->data.x_union.payload, src->data.x_union.payload);
10152 dest->data.x_union.payload->parent.id = ConstParentIdUnion;
10153 dest->data.x_union.payload->parent.data.p_union.union_val = dest;
10154 } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) {
10155 dest->data.x_optional = g->pass1_arena->create<ZigValue>();
10156 copy_const_val(g, dest->data.x_optional, src->data.x_optional);
10157 dest->data.x_optional->parent.id = ConstParentIdOptionalPayload;
10158 dest->data.x_optional->parent.data.p_optional_payload.optional_val = dest;
10159 }
10160}
10161
10162bool optional_value_is_null(ZigValue *val) {
10163 assert(val->special == ConstValSpecialStatic);
10164 if (get_src_ptr_type(val->type) != nullptr) {
10165 if (val->data.x_ptr.special == ConstPtrSpecialNull) {
10166 return true;
10167 } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
10168 return val->data.x_ptr.data.hard_coded_addr.addr == 0;
10169 } else {
10170 return false;
10171 }
10172 } else if (is_opt_err_set(val->type)) {
10173 return val->data.x_err_set == nullptr;
10174 } else {
10175 return val->data.x_optional == nullptr;
10176 }
10177}
10178
10179bool type_is_numeric(ZigType *ty) {
10180 switch (ty->id) {
10181 case ZigTypeIdInvalid:
10182 zig_unreachable();
10183 case ZigTypeIdComptimeFloat:
10184 case ZigTypeIdComptimeInt:
10185 case ZigTypeIdInt:
10186 case ZigTypeIdFloat:
10187 case ZigTypeIdUndefined:
10188 return true;
10189
10190 case ZigTypeIdVector:
10191 return type_is_numeric(ty->data.vector.elem_type);
10192
10193 case ZigTypeIdMetaType:
10194 case ZigTypeIdVoid:
10195 case ZigTypeIdBool:
10196 case ZigTypeIdUnreachable:
10197 case ZigTypeIdPointer:
10198 case ZigTypeIdArray:
10199 case ZigTypeIdStruct:
10200 case ZigTypeIdNull:
10201 case ZigTypeIdOptional:
10202 case ZigTypeIdErrorUnion:
10203 case ZigTypeIdErrorSet:
10204 case ZigTypeIdEnum:
10205 case ZigTypeIdUnion:
10206 case ZigTypeIdFn:
10207 case ZigTypeIdBoundFn:
10208 case ZigTypeIdOpaque:
10209 case ZigTypeIdFnFrame:
10210 case ZigTypeIdAnyFrame:
10211 case ZigTypeIdEnumLiteral:
10212 return false;
10213 }
10214 zig_unreachable();
10215}
10216
10217static void dump_value_indent_error_set(ZigValue *val, int indent) {
10218 fprintf(stderr, "<TODO dump value>\n");
10219}
10220
10221static void dump_value_indent(ZigValue *val, int indent);
10222
10223static void dump_value_indent_ptr(ZigValue *val, int indent) {
10224 switch (val->data.x_ptr.special) {
10225 case ConstPtrSpecialInvalid:
10226 fprintf(stderr, "<!invalid ptr!>\n");
10227 return;
10228 case ConstPtrSpecialNull:
10229 fprintf(stderr, "<null>\n");
10230 return;
10231 case ConstPtrSpecialRef:
10232 fprintf(stderr, "<ref\n");
10233 dump_value_indent(val->data.x_ptr.data.ref.pointee, indent + 1);
10234 break;
10235 case ConstPtrSpecialBaseStruct: {
10236 ZigValue *struct_val = val->data.x_ptr.data.base_struct.struct_val;
10237 size_t field_index = val->data.x_ptr.data.base_struct.field_index;
10238 fprintf(stderr, "<struct %p field %zu\n", struct_val, field_index);
10239 if (struct_val != nullptr) {
10240 ZigValue *field_val = struct_val->data.x_struct.fields[field_index];
10241 if (field_val != nullptr) {
10242 dump_value_indent(field_val, indent + 1);
10243 } else {
10244 for (int i = 0; i < indent; i += 1) {
10245 fprintf(stderr, " ");
10246 }
10247 fprintf(stderr, "(invalid null field)\n");
10248 }
10249 }
10250 break;
10251 }
10252 case ConstPtrSpecialBaseOptionalPayload: {
10253 ZigValue *optional_val = val->data.x_ptr.data.base_optional_payload.optional_val;
10254 fprintf(stderr, "<optional %p payload\n", optional_val);
10255 if (optional_val != nullptr) {
10256 dump_value_indent(optional_val, indent + 1);
10257 }
10258 break;
10259 }
10260 default:
10261 fprintf(stderr, "TODO dump more pointer things\n");
10262 }
10263 for (int i = 0; i < indent; i += 1) {
10264 fprintf(stderr, " ");
10265 }
10266 fprintf(stderr, ">\n");
10267}
10268
10269static void dump_value_indent(ZigValue *val, int indent) {
10270 for (int i = 0; i < indent; i += 1) {
10271 fprintf(stderr, " ");
10272 }
10273 fprintf(stderr, "Value@%p(", val);
10274 if (val->type != nullptr) {
10275 fprintf(stderr, "%s)", buf_ptr(&val->type->name));
10276 } else {
10277 fprintf(stderr, "type=nullptr)");
10278 }
10279 switch (val->special) {
10280 case ConstValSpecialUndef:
10281 fprintf(stderr, "[undefined]\n");
10282 return;
10283 case ConstValSpecialLazy:
10284 fprintf(stderr, "[lazy]\n");
10285 return;
10286 case ConstValSpecialRuntime:
10287 fprintf(stderr, "[runtime]\n");
10288 return;
10289 case ConstValSpecialStatic:
10290 break;
10291 }
10292 if (val->type == nullptr)
10293 return;
10294 switch (val->type->id) {
10295 case ZigTypeIdInvalid:
10296 fprintf(stderr, "<invalid>\n");
10297 return;
10298 case ZigTypeIdUnreachable:
10299 fprintf(stderr, "<unreachable>\n");
10300 return;
10301 case ZigTypeIdUndefined:
10302 fprintf(stderr, "<undefined>\n");
10303 return;
10304 case ZigTypeIdVoid:
10305 fprintf(stderr, "<{}>\n");
10306 return;
10307 case ZigTypeIdMetaType:
10308 fprintf(stderr, "<%s>\n", buf_ptr(&val->data.x_type->name));
10309 return;
10310 case ZigTypeIdBool:
10311 fprintf(stderr, "<%s>\n", val->data.x_bool ? "true" : "false");
10312 return;
10313 case ZigTypeIdComptimeInt:
10314 case ZigTypeIdInt: {
10315 Buf *tmp_buf = buf_alloc();
10316 bigint_append_buf(tmp_buf, &val->data.x_bigint, 10);
10317 fprintf(stderr, "<%s>\n", buf_ptr(tmp_buf));
10318 buf_destroy(tmp_buf);
10319 return;
10320 }
10321 case ZigTypeIdComptimeFloat:
10322 case ZigTypeIdFloat:
10323 fprintf(stderr, "<TODO dump number>\n");
10324 return;
10325
10326 case ZigTypeIdStruct:
10327 fprintf(stderr, "<struct\n");
10328 for (size_t i = 0; i < val->type->data.structure.src_field_count; i += 1) {
10329 for (int j = 0; j < indent; j += 1) {
10330 fprintf(stderr, " ");
10331 }
10332 TypeStructField *field = val->type->data.structure.fields[i];
10333 fprintf(stderr, "%s: ", buf_ptr(field->name));
10334 if (field->is_comptime) {
10335 fprintf(stderr, "<comptime field>");
10336 } else if (val->data.x_struct.fields == nullptr) {
10337 fprintf(stderr, "<null>\n");
10338 } else {
10339 dump_value_indent(val->data.x_struct.fields[i], 1);
10340 }
10341 }
10342 for (int i = 0; i < indent; i += 1) {
10343 fprintf(stderr, " ");
10344 }
10345 fprintf(stderr, ">\n");
10346 return;
10347
10348 case ZigTypeIdOptional:
10349 if (get_src_ptr_type(val->type) != nullptr) {
10350 return dump_value_indent_ptr(val, indent);
10351 } else if (val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) {
10352 return dump_value_indent_error_set(val, indent);
10353 } else {
10354 fprintf(stderr, "<\n");
10355 dump_value_indent(val->data.x_optional, indent + 1);
10356
10357 for (int i = 0; i < indent; i += 1) {
10358 fprintf(stderr, " ");
10359 }
10360 fprintf(stderr, ">\n");
10361 return;
10362 }
10363 case ZigTypeIdErrorUnion:
10364 if (val->data.x_err_union.payload != nullptr) {
10365 fprintf(stderr, "<\n");
10366 dump_value_indent(val->data.x_err_union.payload, indent + 1);
10367 } else {
10368 fprintf(stderr, "<\n");
10369 dump_value_indent(val->data.x_err_union.error_set, 0);
10370 }
10371 for (int i = 0; i < indent; i += 1) {
10372 fprintf(stderr, " ");
10373 }
10374 fprintf(stderr, ">\n");
10375 return;
10376
10377 case ZigTypeIdPointer:
10378 return dump_value_indent_ptr(val, indent);
10379
10380 case ZigTypeIdErrorSet:
10381 return dump_value_indent_error_set(val, indent);
10382
10383 case ZigTypeIdVector:
10384 case ZigTypeIdArray:
10385 case ZigTypeIdNull:
10386 case ZigTypeIdEnum:
10387 case ZigTypeIdUnion:
10388 case ZigTypeIdFn:
10389 case ZigTypeIdBoundFn:
10390 case ZigTypeIdOpaque:
10391 case ZigTypeIdFnFrame:
10392 case ZigTypeIdAnyFrame:
10393 case ZigTypeIdEnumLiteral:
10394 fprintf(stderr, "<TODO dump value>\n");
10395 return;
10396 }
10397 zig_unreachable();
10398}
10399
10400void ZigValue::dump() {
10401 dump_value_indent(this, 0);
10402}
10403
10404// float ops that take a single argument
10405//TODO Powi, Pow, minnum, maxnum, maximum, minimum, copysign, lround, llround, lrint, llrint
10406const char *float_un_op_to_name(BuiltinFnId op) {
10407 switch (op) {
10408 case BuiltinFnIdSqrt:
10409 return "sqrt";
10410 case BuiltinFnIdSin:
10411 return "sin";
10412 case BuiltinFnIdCos:
10413 return "cos";
10414 case BuiltinFnIdTan:
10415 return "tan";
10416 case BuiltinFnIdExp:
10417 return "exp";
10418 case BuiltinFnIdExp2:
10419 return "exp2";
10420 case BuiltinFnIdLog:
10421 return "log";
10422 case BuiltinFnIdLog10:
10423 return "log10";
10424 case BuiltinFnIdLog2:
10425 return "log2";
10426 case BuiltinFnIdFabs:
10427 return "fabs";
10428 case BuiltinFnIdFloor:
10429 return "floor";
10430 case BuiltinFnIdCeil:
10431 return "ceil";
10432 case BuiltinFnIdTrunc:
10433 return "trunc";
10434 case BuiltinFnIdNearbyInt:
10435 return "nearbyint";
10436 case BuiltinFnIdRound:
10437 return "round";
10438 case BuiltinFnIdMulAdd:
10439 return "fma";
10440 default:
10441 zig_unreachable();
10442 }
10443}
src/stage1/analyze.hpp deleted-314
...@@ -1,314 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_ANALYZE_HPP
9#define ZIG_ANALYZE_HPP
10
11#include "all_types.hpp"
12
13void semantic_analyze(CodeGen *g);
14ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
15ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg);
16ErrorMsg *add_token_error_offset(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg,
17 uint32_t bad_index);
18ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg);
19ZigType *new_type_table_entry(ZigTypeId id);
20ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn);
21ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);
22ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type,
23 bool is_const, bool is_volatile, PtrLen ptr_len,
24 uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count,
25 bool allow_zero);
26ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type,
27 bool is_const, bool is_volatile, PtrLen ptr_len,
28 uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count,
29 bool allow_zero, uint32_t vector_index, InferredStructField *inferred_struct_field,
30 ZigValue *sentinel);
31uint64_t type_size(CodeGen *g, ZigType *type_entry);
32uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
33ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
34ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type);
35ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
36ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);
37ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
38ZigType *get_optional_type(CodeGen *g, ZigType *child_type);
39ZigType *get_optional_type2(CodeGen *g, ZigType *child_type);
40ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, ZigValue *sentinel);
41ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);
42ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
43 AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout);
44ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
45ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type);
46ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry);
47ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *full_name, Buf *bare_name);
48ZigType *get_test_fn_type(CodeGen *g);
49ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type);
50bool handle_is_ptr(CodeGen *g, ZigType *type_entry);
51Error emit_error_unless_callconv_allowed_for_target(CodeGen *g, AstNode *source_node, CallingConvention cc);
52uint32_t get_async_frame_align_bytes(CodeGen *g);
53
54bool type_has_bits(CodeGen *g, ZigType *type_entry);
55Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result);
56
57bool fn_returns_c_abi_small_struct(FnTypeId *fn_type_id);
58
59enum ExternPosition {
60 ExternPositionFunctionParameter,
61 ExternPositionFunctionReturn,
62 ExternPositionOther, // array element, struct field, optional element, etc
63};
64
65Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, ExternPosition position, bool *result);
66bool ptr_allows_addr_zero(ZigType *ptr_type);
67
68// Deprecated, use `type_is_nonnull_ptr2`
69bool type_is_nonnull_ptr(CodeGen *g, ZigType *type);
70Error type_is_nonnull_ptr2(CodeGen *g, ZigType *type, bool *result);
71
72ZigType *get_codegen_ptr_type_bail(CodeGen *g, ZigType *type);
73Error get_codegen_ptr_type(CodeGen *g, ZigType *type, ZigType **result);
74
75enum SourceKind {
76 SourceKindRoot,
77 SourceKindPkgMain,
78 SourceKindNonRoot,
79 SourceKindCImport,
80};
81ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *abs_full_path, Buf *source_code,
82 SourceKind source_kind);
83
84ZigVar *find_variable(CodeGen *g, Scope *orig_context, Buf *name, ScopeFnDef **crossed_fndef_scope);
85Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
86Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name);
87void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy);
88void resolve_container_usingnamespace_decls(CodeGen *g, ScopeDecls *decls_scope);
89
90ZigType *get_src_ptr_type(ZigType *type);
91uint32_t get_ptr_align(CodeGen *g, ZigType *type);
92bool get_ptr_const(CodeGen *g, ZigType *type);
93ZigType *validate_var_type(CodeGen *g, AstNodeVariableDeclaration *source_node, ZigType *type_entry);
94ZigType *container_ref_type(ZigType *type_entry);
95bool type_is_complete(ZigType *type_entry);
96bool type_is_resolved(ZigType *type_entry, ResolveStatus status);
97bool type_is_invalid(ZigType *type_entry);
98bool type_is_global_error_set(ZigType *err_set_type);
99ScopeDecls *get_container_scope(ZigType *type_entry);
100TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name);
101TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name);
102TypeUnionField *find_union_type_field(ZigType *type_entry, Buf *name);
103TypeEnumField *find_enum_field_by_tag(ZigType *enum_type, const BigInt *tag);
104TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag);
105
106bool is_ref(ZigType *type_entry);
107bool is_array_ref(ZigType *type_entry);
108bool is_container_ref(ZigType *type_entry);
109Error is_valid_vector_elem_type(CodeGen *g, ZigType *elem_type, bool *result);
110void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
111ZigFn *scope_fn_entry(Scope *scope);
112ZigPackage *scope_package(Scope *scope);
113ZigType *get_scope_import(Scope *scope);
114ScopeTypeOf *get_scope_typeof(Scope *scope);
115void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);
116ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
117 bool is_const, ZigValue *init_value, Tld *src_tld, ZigType *var_type);
118ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
119void append_namespace_qualification(CodeGen *g, Buf *buf, ZigType *container_type);
120ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
121void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, CallingConvention cc, size_t param_count_alloc);
122AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
123Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);
124void complete_enum(CodeGen *g, ZigType *enum_type);
125bool ir_get_var_is_comptime(ZigVar *var);
126bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b);
127void eval_min_max_value(CodeGen *g, ZigType *type_entry, ZigValue *const_val, bool is_max);
128void eval_min_max_value_int(CodeGen *g, ZigType *int_type, BigInt *bigint, bool is_max);
129
130void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val);
131
132ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type, ZigType *import, Buf *bare_name);
133ScopeBlock *create_block_scope(CodeGen *g, AstNode *node, Scope *parent);
134ScopeDefer *create_defer_scope(CodeGen *g, AstNode *node, Scope *parent);
135ScopeDeferExpr *create_defer_expr_scope(CodeGen *g, AstNode *node, Scope *parent);
136Scope *create_var_scope(CodeGen *g, AstNode *node, Scope *parent, ZigVar *var);
137ScopeCImport *create_cimport_scope(CodeGen *g, AstNode *node, Scope *parent);
138ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent);
139ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent);
140ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry);
141Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
142Scope *create_nosuspend_scope(CodeGen *g, AstNode *node, Scope *parent);
143Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, Stage1ZirInst *is_comptime);
144Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent);
145ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent);
146
147void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str, bool move_str);
148ZigValue *create_const_str_lit(CodeGen *g, Buf *str);
149ZigValue *create_sentineled_str_lit(CodeGen *g, Buf *str, ZigValue *sentinel);
150
151void init_const_bigint(ZigValue *const_val, ZigType *type, const BigInt *bigint);
152ZigValue *create_const_bigint(CodeGen *g, ZigType *type, const BigInt *bigint);
153
154void init_const_unsigned_negative(ZigValue *const_val, ZigType *type, uint64_t x, bool negative);
155ZigValue *create_const_unsigned_negative(CodeGen *g, ZigType *type, uint64_t x, bool negative);
156
157void init_const_signed(ZigValue *const_val, ZigType *type, int64_t x);
158ZigValue *create_const_signed(CodeGen *g, ZigType *type, int64_t x);
159
160void init_const_usize(CodeGen *g, ZigValue *const_val, uint64_t x);
161ZigValue *create_const_usize(CodeGen *g, uint64_t x);
162
163void init_const_float(ZigValue *const_val, ZigType *type, double value);
164ZigValue *create_const_float(CodeGen *g, ZigType *type, double value);
165
166void init_const_enum(ZigValue *const_val, ZigType *type, const BigInt *tag);
167ZigValue *create_const_enum(CodeGen *g, ZigType *type, const BigInt *tag);
168
169void init_const_bool(CodeGen *g, ZigValue *const_val, bool value);
170ZigValue *create_const_bool(CodeGen *g, bool value);
171
172void init_const_type(CodeGen *g, ZigValue *const_val, ZigType *type_value);
173ZigValue *create_const_type(CodeGen *g, ZigType *type_value);
174
175void init_const_runtime(ZigValue *const_val, ZigType *type);
176ZigValue *create_const_runtime(CodeGen *g, ZigType *type);
177
178void init_const_ptr_ref(CodeGen *g, ZigValue *const_val, ZigValue *pointee_val, bool is_const);
179ZigValue *create_const_ptr_ref(CodeGen *g, ZigValue *pointee_val, bool is_const);
180
181void init_const_ptr_hard_coded_addr(CodeGen *g, ZigValue *const_val, ZigType *pointee_type,
182 size_t addr, bool is_const);
183ZigValue *create_const_ptr_hard_coded_addr(CodeGen *g, ZigType *pointee_type,
184 size_t addr, bool is_const);
185
186void init_const_ptr_array(CodeGen *g, ZigValue *const_val, ZigValue *array_val,
187 size_t elem_index, bool is_const, PtrLen ptr_len);
188ZigValue *create_const_ptr_array(CodeGen *g, ZigValue *array_val, size_t elem_index,
189 bool is_const, PtrLen ptr_len);
190
191void init_const_slice(CodeGen *g, ZigValue *const_val, ZigValue *array_val,
192 size_t start, size_t len, bool is_const, ZigValue *sentinel);
193ZigValue *create_const_slice(CodeGen *g, ZigValue *array_val, size_t start, size_t len, bool is_const, ZigValue *sentinel);
194
195void init_const_null(ZigValue *const_val, ZigType *type);
196ZigValue *create_const_null(CodeGen *g, ZigType *type);
197
198void init_const_fn(ZigValue *const_val, ZigFn *fn);
199ZigValue *create_const_fn(CodeGen *g, ZigFn *fn);
200
201ZigValue **alloc_const_vals_ptrs(CodeGen *g, size_t count);
202ZigValue **realloc_const_vals_ptrs(CodeGen *g, ZigValue **ptr, size_t old_count, size_t new_count);
203
204TypeStructField **alloc_type_struct_fields(size_t count);
205TypeStructField **realloc_type_struct_fields(TypeStructField **ptr, size_t old_count, size_t new_count);
206
207ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
208void expand_undef_array(CodeGen *g, ZigValue *const_val);
209void expand_undef_struct(CodeGen *g, ZigValue *const_val);
210void update_compile_var(CodeGen *g, Buf *name, ZigValue *value);
211
212const char *type_id_name(ZigTypeId id);
213ZigTypeId type_id_at_index(size_t index);
214size_t type_id_len();
215size_t type_id_index(ZigType *entry);
216ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id);
217bool optional_value_is_null(ZigValue *val);
218
219uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry);
220ZigType *get_align_amt_type(CodeGen *g);
221ZigPackage *new_anonymous_package(void);
222
223Buf *const_value_to_buffer(ZigValue *const_val);
224void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage, CallingConvention cc);
225void add_var_export(CodeGen *g, ZigVar *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage);
226
227
228ZigValue *get_builtin_value(CodeGen *codegen, const char *name);
229ZigType *get_builtin_type(CodeGen *codegen, const char *name);
230ZigType *get_stack_trace_type(CodeGen *g);
231bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node);
232
233ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry);
234
235bool fn_type_can_fail(FnTypeId *fn_type_id);
236bool type_can_fail(ZigType *type_entry);
237bool fn_eval_cacheable(Scope *scope, ZigType *return_type);
238AstNode *type_decl_node(ZigType *type_entry);
239
240Error get_primitive_type(CodeGen *g, Buf *name, ZigType **result);
241
242bool calling_convention_allows_zig_types(CallingConvention cc);
243const char *calling_convention_name(CallingConvention cc);
244
245const char *address_space_name(AddressSpace as);
246
247Error ATTRIBUTE_MUST_USE file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents);
248
249void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
250X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
251bool type_is_c_abi_int_bail(CodeGen *g, ZigType *ty);
252Error type_is_c_abi_int(CodeGen *g, ZigType *ty, bool *result);
253bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
254const char *container_string(ContainerKind kind);
255
256uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);
257
258enum ReqCompTime {
259 ReqCompTimeInvalid,
260 ReqCompTimeNo,
261 ReqCompTimeYes,
262};
263ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);
264
265OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);
266
267Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
268 ZigValue *const_val, ZigType *wanted_type);
269
270void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn);
271Buf *type_bare_name(ZigType *t);
272Buf *type_h_name(ZigType *t);
273
274LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type);
275LLVMTypeRef get_llvm_c_abi_type(CodeGen *g, ZigType *type);
276ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type);
277
278void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_path, bool translate_c,
279 FileExt source_kind);
280
281void src_assert_impl(bool ok, AstNode *source_node, const char *file, unsigned int line);
282bool is_container(ZigType *type_entry);
283ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
284 Buf *type_name, UndefAllowed undef);
285
286void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);
287bool fn_is_async(ZigFn *fn);
288CallingConvention cc_from_fn_proto(AstNodeFnProto *fn_proto);
289bool is_valid_return_type(ZigType* type);
290bool is_valid_param_type(ZigType* type);
291
292Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *type_val, uint32_t *abi_align);
293Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ZigValue *type_val,
294 size_t *abi_size, size_t *size_in_bits);
295Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent_type,
296 ZigValue *parent_type_val, bool *is_zero_bits);
297ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field);
298ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field);
299
300void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn);
301
302Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str,
303 ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path);
304ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry);
305bool is_anon_container(ZigType *ty);
306void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src);
307bool type_has_optional_repr(ZigType *ty);
308bool is_opt_err_set(ZigType *ty);
309bool type_is_numeric(ZigType *ty);
310const char *float_un_op_to_name(BuiltinFnId op);
311
312#define src_assert(OK, SOURCE_NODE) src_assert_impl((OK), (SOURCE_NODE), __FILE__, __LINE__)
313
314#endif
src/stage1/astgen.cpp deleted-8339
...@@ -1,8339 +0,0 @@
1/*
2 * Copyright (c) 2021 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "astgen.hpp"
9#include "analyze.hpp"
10#include "util.hpp"
11#include "os.hpp"
12#include "parser.hpp"
13
14struct Stage1AstGen {
15 CodeGen *codegen;
16 Stage1Zir *exec;
17 Stage1ZirBasicBlock *current_basic_block;
18 AstNode *main_block_node;
19 size_t next_debug_id;
20 ZigFn *fn;
21 bool in_c_import_scope;
22};
23
24static Stage1ZirInst *astgen_node(Stage1AstGen *ag, AstNode *node, Scope *scope);
25static Stage1ZirInst *astgen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scope, LVal lval,
26 ResultLoc *result_loc);
27
28static Stage1ZirInst *ir_lval_wrap(Stage1AstGen *ag, Scope *scope, Stage1ZirInst *value, LVal lval,
29 ResultLoc *result_loc);
30static Stage1ZirInst *ir_expr_wrap(Stage1AstGen *ag, Scope *scope, Stage1ZirInst *inst,
31 ResultLoc *result_loc);
32static Stage1ZirInst *astgen_union_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
33 Stage1ZirInst *union_type, Stage1ZirInst *field_name, AstNode *expr_node,
34 LVal lval, ResultLoc *parent_result_loc);
35static ResultLocCast *ir_build_cast_result_loc(Stage1AstGen *ag, Stage1ZirInst *dest_type,
36 ResultLoc *parent_result_loc);
37static ZigVar *ir_create_var(Stage1AstGen *ag, AstNode *node, Scope *scope, Buf *name,
38 bool src_is_const, bool gen_is_const, bool is_shadowable, Stage1ZirInst *is_comptime);
39static void build_decl_var_and_init(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
40 ZigVar *var, Stage1ZirInst *init, const char *name_hint, Stage1ZirInst *is_comptime);
41
42static void ir_assert_impl(bool ok, Stage1ZirInst *source_instruction, char const *file, unsigned int line) {
43 if (ok) return;
44 src_assert_impl(ok, source_instruction->source_node, file, line);
45}
46
47static ErrorMsg *exec_add_error_node(CodeGen *codegen, Stage1Zir *exec, AstNode *source_node, Buf *msg) {
48 ErrorMsg *err_msg = add_node_error(codegen, source_node, msg);
49 invalidate_exec(exec, err_msg);
50 return err_msg;
51}
52
53
54#define ir_assert(OK, SOURCE_INSTRUCTION) ir_assert_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__)
55
56
57static bool instr_is_unreachable(Stage1ZirInst *instruction) {
58 switch (instruction->id) {
59 case Stage1ZirInstIdCondBr:
60 case Stage1ZirInstIdReturn:
61 case Stage1ZirInstIdBr:
62 case Stage1ZirInstIdUnreachable:
63 case Stage1ZirInstIdSwitchBr:
64 case Stage1ZirInstIdPanic:
65 return true;
66 default:
67 return false;
68 }
69}
70
71void destroy_instruction_src(Stage1ZirInst *inst) {
72 switch (inst->id) {
73 case Stage1ZirInstIdInvalid:
74 zig_unreachable();
75 case Stage1ZirInstIdReturn:
76 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstReturn *>(inst));
77 case Stage1ZirInstIdConst:
78 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstConst *>(inst));
79 case Stage1ZirInstIdBinOp:
80 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstBinOp *>(inst));
81 case Stage1ZirInstIdMergeErrSets:
82 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstMergeErrSets *>(inst));
83 case Stage1ZirInstIdDeclVar:
84 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstDeclVar *>(inst));
85 case Stage1ZirInstIdCall:
86 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCall *>(inst));
87 case Stage1ZirInstIdCallExtra:
88 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCallExtra *>(inst));
89 case Stage1ZirInstIdAsyncCallExtra:
90 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstAsyncCallExtra *>(inst));
91 case Stage1ZirInstIdUnOp:
92 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstUnOp *>(inst));
93 case Stage1ZirInstIdCondBr:
94 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCondBr *>(inst));
95 case Stage1ZirInstIdBr:
96 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstBr *>(inst));
97 case Stage1ZirInstIdPhi:
98 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstPhi *>(inst));
99 case Stage1ZirInstIdContainerInitList:
100 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstContainerInitList *>(inst));
101 case Stage1ZirInstIdContainerInitFields:
102 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstContainerInitFields *>(inst));
103 case Stage1ZirInstIdUnreachable:
104 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstUnreachable *>(inst));
105 case Stage1ZirInstIdElemPtr:
106 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstElemPtr *>(inst));
107 case Stage1ZirInstIdVarPtr:
108 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstVarPtr *>(inst));
109 case Stage1ZirInstIdLoadPtr:
110 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstLoadPtr *>(inst));
111 case Stage1ZirInstIdStorePtr:
112 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstStorePtr *>(inst));
113 case Stage1ZirInstIdTypeOf:
114 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstTypeOf *>(inst));
115 case Stage1ZirInstIdFieldPtr:
116 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstFieldPtr *>(inst));
117 case Stage1ZirInstIdSetCold:
118 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSetCold *>(inst));
119 case Stage1ZirInstIdSetRuntimeSafety:
120 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSetRuntimeSafety *>(inst));
121 case Stage1ZirInstIdSetFloatMode:
122 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSetFloatMode *>(inst));
123 case Stage1ZirInstIdArrayType:
124 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstArrayType *>(inst));
125 case Stage1ZirInstIdSliceType:
126 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSliceType *>(inst));
127 case Stage1ZirInstIdAnyFrameType:
128 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstAnyFrameType *>(inst));
129 case Stage1ZirInstIdAsm:
130 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstAsm *>(inst));
131 case Stage1ZirInstIdSizeOf:
132 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSizeOf *>(inst));
133 case Stage1ZirInstIdTestNonNull:
134 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstTestNonNull *>(inst));
135 case Stage1ZirInstIdOptionalUnwrapPtr:
136 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstOptionalUnwrapPtr *>(inst));
137 case Stage1ZirInstIdPopCount:
138 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstPopCount *>(inst));
139 case Stage1ZirInstIdClz:
140 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstClz *>(inst));
141 case Stage1ZirInstIdCtz:
142 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCtz *>(inst));
143 case Stage1ZirInstIdBswap:
144 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstBswap *>(inst));
145 case Stage1ZirInstIdBitReverse:
146 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstBitReverse *>(inst));
147 case Stage1ZirInstIdSwitchBr:
148 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSwitchBr *>(inst));
149 case Stage1ZirInstIdSwitchVar:
150 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSwitchVar *>(inst));
151 case Stage1ZirInstIdSwitchElseVar:
152 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSwitchElseVar *>(inst));
153 case Stage1ZirInstIdSwitchTarget:
154 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSwitchTarget *>(inst));
155 case Stage1ZirInstIdImport:
156 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstImport *>(inst));
157 case Stage1ZirInstIdRef:
158 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstRef *>(inst));
159 case Stage1ZirInstIdCompileErr:
160 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCompileErr *>(inst));
161 case Stage1ZirInstIdCompileLog:
162 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCompileLog *>(inst));
163 case Stage1ZirInstIdErrName:
164 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstErrName *>(inst));
165 case Stage1ZirInstIdCImport:
166 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCImport *>(inst));
167 case Stage1ZirInstIdCInclude:
168 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCInclude *>(inst));
169 case Stage1ZirInstIdCDefine:
170 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCDefine *>(inst));
171 case Stage1ZirInstIdCUndef:
172 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCUndef *>(inst));
173 case Stage1ZirInstIdEmbedFile:
174 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstEmbedFile *>(inst));
175 case Stage1ZirInstIdCmpxchg:
176 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCmpxchg *>(inst));
177 case Stage1ZirInstIdFence:
178 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstFence *>(inst));
179 case Stage1ZirInstIdReduce:
180 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstReduce *>(inst));
181 case Stage1ZirInstIdTruncate:
182 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstTruncate *>(inst));
183 case Stage1ZirInstIdIntCast:
184 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstIntCast *>(inst));
185 case Stage1ZirInstIdFloatCast:
186 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstFloatCast *>(inst));
187 case Stage1ZirInstIdErrSetCast:
188 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstErrSetCast *>(inst));
189 case Stage1ZirInstIdIntToFloat:
190 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstIntToFloat *>(inst));
191 case Stage1ZirInstIdFloatToInt:
192 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstFloatToInt *>(inst));
193 case Stage1ZirInstIdBoolToInt:
194 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstBoolToInt *>(inst));
195 case Stage1ZirInstIdVectorType:
196 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstVectorType *>(inst));
197 case Stage1ZirInstIdShuffleVector:
198 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstShuffleVector *>(inst));
199 case Stage1ZirInstIdSelect:
200 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSelect *>(inst));
201 case Stage1ZirInstIdSplat:
202 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSplat *>(inst));
203 case Stage1ZirInstIdBoolNot:
204 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstBoolNot *>(inst));
205 case Stage1ZirInstIdMemset:
206 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstMemset *>(inst));
207 case Stage1ZirInstIdMemcpy:
208 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstMemcpy *>(inst));
209 case Stage1ZirInstIdSlice:
210 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSlice *>(inst));
211 case Stage1ZirInstIdBreakpoint:
212 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstBreakpoint *>(inst));
213 case Stage1ZirInstIdReturnAddress:
214 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstReturnAddress *>(inst));
215 case Stage1ZirInstIdFrameAddress:
216 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstFrameAddress *>(inst));
217 case Stage1ZirInstIdFrameHandle:
218 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstFrameHandle *>(inst));
219 case Stage1ZirInstIdFrameType:
220 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstFrameType *>(inst));
221 case Stage1ZirInstIdFrameSize:
222 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstFrameSize *>(inst));
223 case Stage1ZirInstIdAlignOf:
224 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstAlignOf *>(inst));
225 case Stage1ZirInstIdOverflowOp:
226 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstOverflowOp *>(inst));
227 case Stage1ZirInstIdTestErr:
228 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstTestErr *>(inst));
229 case Stage1ZirInstIdUnwrapErrCode:
230 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstUnwrapErrCode *>(inst));
231 case Stage1ZirInstIdUnwrapErrPayload:
232 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstUnwrapErrPayload *>(inst));
233 case Stage1ZirInstIdFnProto:
234 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstFnProto *>(inst));
235 case Stage1ZirInstIdTestComptime:
236 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstTestComptime *>(inst));
237 case Stage1ZirInstIdPtrCast:
238 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstPtrCast *>(inst));
239 case Stage1ZirInstIdBitCast:
240 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstBitCast *>(inst));
241 case Stage1ZirInstIdPtrToInt:
242 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstPtrToInt *>(inst));
243 case Stage1ZirInstIdIntToPtr:
244 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstIntToPtr *>(inst));
245 case Stage1ZirInstIdIntToEnum:
246 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstIntToEnum *>(inst));
247 case Stage1ZirInstIdIntToErr:
248 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstIntToErr *>(inst));
249 case Stage1ZirInstIdErrToInt:
250 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstErrToInt *>(inst));
251 case Stage1ZirInstIdCheckSwitchProngsUnderNo:
252 case Stage1ZirInstIdCheckSwitchProngsUnderYes:
253 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCheckSwitchProngs *>(inst));
254 case Stage1ZirInstIdCheckStatementIsVoid:
255 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCheckStatementIsVoid *>(inst));
256 case Stage1ZirInstIdTypeName:
257 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstTypeName *>(inst));
258 case Stage1ZirInstIdTagName:
259 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstTagName *>(inst));
260 case Stage1ZirInstIdPtrType:
261 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstPtrType *>(inst));
262 case Stage1ZirInstIdPtrTypeSimple:
263 case Stage1ZirInstIdPtrTypeSimpleConst:
264 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstPtrTypeSimple *>(inst));
265 case Stage1ZirInstIdDeclRef:
266 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstDeclRef *>(inst));
267 case Stage1ZirInstIdPanic:
268 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstPanic *>(inst));
269 case Stage1ZirInstIdFieldParentPtr:
270 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstFieldParentPtr *>(inst));
271 case Stage1ZirInstIdOffsetOf:
272 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstOffsetOf *>(inst));
273 case Stage1ZirInstIdBitOffsetOf:
274 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstBitOffsetOf *>(inst));
275 case Stage1ZirInstIdTypeInfo:
276 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstTypeInfo *>(inst));
277 case Stage1ZirInstIdType:
278 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstType *>(inst));
279 case Stage1ZirInstIdHasField:
280 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstHasField *>(inst));
281 case Stage1ZirInstIdSetEvalBranchQuota:
282 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSetEvalBranchQuota *>(inst));
283 case Stage1ZirInstIdAlignCast:
284 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstAlignCast *>(inst));
285 case Stage1ZirInstIdImplicitCast:
286 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstImplicitCast *>(inst));
287 case Stage1ZirInstIdResolveResult:
288 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstResolveResult *>(inst));
289 case Stage1ZirInstIdResetResult:
290 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstResetResult *>(inst));
291 case Stage1ZirInstIdSetAlignStack:
292 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSetAlignStack *>(inst));
293 case Stage1ZirInstIdArgTypeAllowVarFalse:
294 case Stage1ZirInstIdArgTypeAllowVarTrue:
295 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstArgType *>(inst));
296 case Stage1ZirInstIdExport:
297 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstExport *>(inst));
298 case Stage1ZirInstIdExtern:
299 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstExtern *>(inst));
300 case Stage1ZirInstIdErrorReturnTrace:
301 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstErrorReturnTrace *>(inst));
302 case Stage1ZirInstIdErrorUnion:
303 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstErrorUnion *>(inst));
304 case Stage1ZirInstIdAtomicRmw:
305 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstAtomicRmw *>(inst));
306 case Stage1ZirInstIdSaveErrRetAddr:
307 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSaveErrRetAddr *>(inst));
308 case Stage1ZirInstIdAddImplicitReturnType:
309 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstAddImplicitReturnType *>(inst));
310 case Stage1ZirInstIdFloatOp:
311 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstFloatOp *>(inst));
312 case Stage1ZirInstIdMulAdd:
313 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstMulAdd *>(inst));
314 case Stage1ZirInstIdAtomicLoad:
315 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstAtomicLoad *>(inst));
316 case Stage1ZirInstIdAtomicStore:
317 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstAtomicStore *>(inst));
318 case Stage1ZirInstIdEnumToInt:
319 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstEnumToInt *>(inst));
320 case Stage1ZirInstIdCheckRuntimeScope:
321 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCheckRuntimeScope *>(inst));
322 case Stage1ZirInstIdHasDecl:
323 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstHasDecl *>(inst));
324 case Stage1ZirInstIdUndeclaredIdent:
325 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstUndeclaredIdent *>(inst));
326 case Stage1ZirInstIdAlloca:
327 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstAlloca *>(inst));
328 case Stage1ZirInstIdEndExpr:
329 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstEndExpr *>(inst));
330 case Stage1ZirInstIdUnionInitNamedField:
331 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstUnionInitNamedField *>(inst));
332 case Stage1ZirInstIdSuspendBegin:
333 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSuspendBegin *>(inst));
334 case Stage1ZirInstIdSuspendFinish:
335 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSuspendFinish *>(inst));
336 case Stage1ZirInstIdResume:
337 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstResume *>(inst));
338 case Stage1ZirInstIdAwait:
339 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstAwait *>(inst));
340 case Stage1ZirInstIdSpillBegin:
341 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSpillBegin *>(inst));
342 case Stage1ZirInstIdSpillEnd:
343 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSpillEnd *>(inst));
344 case Stage1ZirInstIdCallArgs:
345 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstCallArgs *>(inst));
346 case Stage1ZirInstIdWasmMemorySize:
347 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstWasmMemorySize *>(inst));
348 case Stage1ZirInstIdWasmMemoryGrow:
349 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstWasmMemoryGrow *>(inst));
350 case Stage1ZirInstIdSrc:
351 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSrc *>(inst));
352 case Stage1ZirInstIdPrefetch:
353 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstPrefetch *>(inst));
354 case Stage1ZirInstIdAddrSpaceCast:
355 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstAddrSpaceCast *>(inst));
356 }
357 zig_unreachable();
358}
359
360
361bool ir_should_inline(Stage1Zir *exec, Scope *scope) {
362 if (exec->is_inline)
363 return true;
364
365 while (scope != nullptr) {
366 if (scope->id == ScopeIdCompTime)
367 return true;
368 if (scope->id == ScopeIdTypeOf)
369 return false;
370 if (scope->id == ScopeIdFnDef)
371 break;
372 scope = scope->parent;
373 }
374 return false;
375}
376
377static void ir_instruction_append(Stage1ZirBasicBlock *basic_block, Stage1ZirInst *instruction) {
378 assert(basic_block);
379 assert(instruction);
380 basic_block->instruction_list.append(instruction);
381}
382
383static size_t irb_next_debug_id(Stage1AstGen *ag) {
384 size_t result = ag->next_debug_id;
385 ag->next_debug_id += 1;
386 return result;
387}
388
389static void ir_ref_bb(Stage1ZirBasicBlock *bb) {
390 bb->ref_count += 1;
391}
392
393static void ir_ref_instruction(Stage1ZirInst *instruction, Stage1ZirBasicBlock *cur_bb) {
394 assert(instruction->id != Stage1ZirInstIdInvalid);
395 instruction->ref_count += 1;
396 if (instruction->owner_bb != cur_bb && !instr_is_unreachable(instruction)
397 && instruction->id != Stage1ZirInstIdConst)
398 {
399 ir_ref_bb(instruction->owner_bb);
400 }
401}
402
403static Stage1ZirBasicBlock *ir_create_basic_block(Stage1AstGen *ag, Scope *scope, const char *name_hint) {
404 Stage1ZirBasicBlock *result = heap::c_allocator.create<Stage1ZirBasicBlock>();
405 result->scope = scope;
406 result->name_hint = name_hint;
407 result->debug_id = irb_next_debug_id(ag);
408 result->index = UINT32_MAX; // set later
409 return result;
410}
411
412static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstDeclVar *) {
413 return Stage1ZirInstIdDeclVar;
414}
415
416static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBr *) {
417 return Stage1ZirInstIdBr;
418}
419
420static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCondBr *) {
421 return Stage1ZirInstIdCondBr;
422}
423
424static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSwitchBr *) {
425 return Stage1ZirInstIdSwitchBr;
426}
427
428static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSwitchVar *) {
429 return Stage1ZirInstIdSwitchVar;
430}
431
432static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSwitchElseVar *) {
433 return Stage1ZirInstIdSwitchElseVar;
434}
435
436static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSwitchTarget *) {
437 return Stage1ZirInstIdSwitchTarget;
438}
439
440static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPhi *) {
441 return Stage1ZirInstIdPhi;
442}
443
444static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstUnOp *) {
445 return Stage1ZirInstIdUnOp;
446}
447
448static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBinOp *) {
449 return Stage1ZirInstIdBinOp;
450}
451
452static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstMergeErrSets *) {
453 return Stage1ZirInstIdMergeErrSets;
454}
455
456static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstLoadPtr *) {
457 return Stage1ZirInstIdLoadPtr;
458}
459
460static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstStorePtr *) {
461 return Stage1ZirInstIdStorePtr;
462}
463
464static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFieldPtr *) {
465 return Stage1ZirInstIdFieldPtr;
466}
467
468static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstElemPtr *) {
469 return Stage1ZirInstIdElemPtr;
470}
471
472static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstVarPtr *) {
473 return Stage1ZirInstIdVarPtr;
474}
475
476static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCall *) {
477 return Stage1ZirInstIdCall;
478}
479
480static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCallArgs *) {
481 return Stage1ZirInstIdCallArgs;
482}
483
484static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCallExtra *) {
485 return Stage1ZirInstIdCallExtra;
486}
487
488static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAsyncCallExtra *) {
489 return Stage1ZirInstIdAsyncCallExtra;
490}
491
492static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstConst *) {
493 return Stage1ZirInstIdConst;
494}
495
496static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstReturn *) {
497 return Stage1ZirInstIdReturn;
498}
499
500static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstContainerInitList *) {
501 return Stage1ZirInstIdContainerInitList;
502}
503
504static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstContainerInitFields *) {
505 return Stage1ZirInstIdContainerInitFields;
506}
507
508static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstUnreachable *) {
509 return Stage1ZirInstIdUnreachable;
510}
511
512static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTypeOf *) {
513 return Stage1ZirInstIdTypeOf;
514}
515
516static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSetCold *) {
517 return Stage1ZirInstIdSetCold;
518}
519
520static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSetRuntimeSafety *) {
521 return Stage1ZirInstIdSetRuntimeSafety;
522}
523
524static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSetFloatMode *) {
525 return Stage1ZirInstIdSetFloatMode;
526}
527
528static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstArrayType *) {
529 return Stage1ZirInstIdArrayType;
530}
531
532static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAnyFrameType *) {
533 return Stage1ZirInstIdAnyFrameType;
534}
535
536static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSliceType *) {
537 return Stage1ZirInstIdSliceType;
538}
539
540static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAsm *) {
541 return Stage1ZirInstIdAsm;
542}
543
544static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSizeOf *) {
545 return Stage1ZirInstIdSizeOf;
546}
547
548static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTestNonNull *) {
549 return Stage1ZirInstIdTestNonNull;
550}
551
552static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstOptionalUnwrapPtr *) {
553 return Stage1ZirInstIdOptionalUnwrapPtr;
554}
555
556static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstClz *) {
557 return Stage1ZirInstIdClz;
558}
559
560static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCtz *) {
561 return Stage1ZirInstIdCtz;
562}
563
564static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPopCount *) {
565 return Stage1ZirInstIdPopCount;
566}
567
568static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBswap *) {
569 return Stage1ZirInstIdBswap;
570}
571
572static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBitReverse *) {
573 return Stage1ZirInstIdBitReverse;
574}
575
576static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstImport *) {
577 return Stage1ZirInstIdImport;
578}
579
580static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCImport *) {
581 return Stage1ZirInstIdCImport;
582}
583
584static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCInclude *) {
585 return Stage1ZirInstIdCInclude;
586}
587
588static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCDefine *) {
589 return Stage1ZirInstIdCDefine;
590}
591
592static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCUndef *) {
593 return Stage1ZirInstIdCUndef;
594}
595
596static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstRef *) {
597 return Stage1ZirInstIdRef;
598}
599
600static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCompileErr *) {
601 return Stage1ZirInstIdCompileErr;
602}
603
604static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCompileLog *) {
605 return Stage1ZirInstIdCompileLog;
606}
607
608static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstErrName *) {
609 return Stage1ZirInstIdErrName;
610}
611
612static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstEmbedFile *) {
613 return Stage1ZirInstIdEmbedFile;
614}
615
616static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCmpxchg *) {
617 return Stage1ZirInstIdCmpxchg;
618}
619
620static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFence *) {
621 return Stage1ZirInstIdFence;
622}
623
624static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstReduce *) {
625 return Stage1ZirInstIdReduce;
626}
627
628static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTruncate *) {
629 return Stage1ZirInstIdTruncate;
630}
631
632static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstIntCast *) {
633 return Stage1ZirInstIdIntCast;
634}
635
636static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFloatCast *) {
637 return Stage1ZirInstIdFloatCast;
638}
639
640static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstIntToFloat *) {
641 return Stage1ZirInstIdIntToFloat;
642}
643
644static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFloatToInt *) {
645 return Stage1ZirInstIdFloatToInt;
646}
647
648static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBoolToInt *) {
649 return Stage1ZirInstIdBoolToInt;
650}
651
652static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstVectorType *) {
653 return Stage1ZirInstIdVectorType;
654}
655
656static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstShuffleVector *) {
657 return Stage1ZirInstIdShuffleVector;
658}
659
660static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSelect *) {
661 return Stage1ZirInstIdSelect;
662}
663
664static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSplat *) {
665 return Stage1ZirInstIdSplat;
666}
667
668static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBoolNot *) {
669 return Stage1ZirInstIdBoolNot;
670}
671
672static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstMemset *) {
673 return Stage1ZirInstIdMemset;
674}
675
676static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstMemcpy *) {
677 return Stage1ZirInstIdMemcpy;
678}
679
680static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSlice *) {
681 return Stage1ZirInstIdSlice;
682}
683
684static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBreakpoint *) {
685 return Stage1ZirInstIdBreakpoint;
686}
687
688static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstReturnAddress *) {
689 return Stage1ZirInstIdReturnAddress;
690}
691
692static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFrameAddress *) {
693 return Stage1ZirInstIdFrameAddress;
694}
695
696static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFrameHandle *) {
697 return Stage1ZirInstIdFrameHandle;
698}
699
700static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFrameType *) {
701 return Stage1ZirInstIdFrameType;
702}
703
704static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFrameSize *) {
705 return Stage1ZirInstIdFrameSize;
706}
707
708static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAlignOf *) {
709 return Stage1ZirInstIdAlignOf;
710}
711
712static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstOverflowOp *) {
713 return Stage1ZirInstIdOverflowOp;
714}
715
716static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTestErr *) {
717 return Stage1ZirInstIdTestErr;
718}
719
720static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstMulAdd *) {
721 return Stage1ZirInstIdMulAdd;
722}
723
724static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFloatOp *) {
725 return Stage1ZirInstIdFloatOp;
726}
727
728static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstUnwrapErrCode *) {
729 return Stage1ZirInstIdUnwrapErrCode;
730}
731
732static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstUnwrapErrPayload *) {
733 return Stage1ZirInstIdUnwrapErrPayload;
734}
735
736static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFnProto *) {
737 return Stage1ZirInstIdFnProto;
738}
739
740static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTestComptime *) {
741 return Stage1ZirInstIdTestComptime;
742}
743
744static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPtrCast *) {
745 return Stage1ZirInstIdPtrCast;
746}
747
748static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBitCast *) {
749 return Stage1ZirInstIdBitCast;
750}
751
752static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstIntToPtr *) {
753 return Stage1ZirInstIdIntToPtr;
754}
755
756static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPtrToInt *) {
757 return Stage1ZirInstIdPtrToInt;
758}
759
760static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstIntToEnum *) {
761 return Stage1ZirInstIdIntToEnum;
762}
763
764static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstEnumToInt *) {
765 return Stage1ZirInstIdEnumToInt;
766}
767
768static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstIntToErr *) {
769 return Stage1ZirInstIdIntToErr;
770}
771
772static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstErrToInt *) {
773 return Stage1ZirInstIdErrToInt;
774}
775
776static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCheckStatementIsVoid *) {
777 return Stage1ZirInstIdCheckStatementIsVoid;
778}
779
780static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTypeName *) {
781 return Stage1ZirInstIdTypeName;
782}
783
784static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstDeclRef *) {
785 return Stage1ZirInstIdDeclRef;
786}
787
788static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPanic *) {
789 return Stage1ZirInstIdPanic;
790}
791
792static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTagName *) {
793 return Stage1ZirInstIdTagName;
794}
795
796static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFieldParentPtr *) {
797 return Stage1ZirInstIdFieldParentPtr;
798}
799
800static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstOffsetOf *) {
801 return Stage1ZirInstIdOffsetOf;
802}
803
804static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBitOffsetOf *) {
805 return Stage1ZirInstIdBitOffsetOf;
806}
807
808static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTypeInfo *) {
809 return Stage1ZirInstIdTypeInfo;
810}
811
812static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstType *) {
813 return Stage1ZirInstIdType;
814}
815
816static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstHasField *) {
817 return Stage1ZirInstIdHasField;
818}
819
820static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSetEvalBranchQuota *) {
821 return Stage1ZirInstIdSetEvalBranchQuota;
822}
823
824static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPtrType *) {
825 return Stage1ZirInstIdPtrType;
826}
827
828static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAlignCast *) {
829 return Stage1ZirInstIdAlignCast;
830}
831
832static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstImplicitCast *) {
833 return Stage1ZirInstIdImplicitCast;
834}
835
836static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstResolveResult *) {
837 return Stage1ZirInstIdResolveResult;
838}
839
840static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstResetResult *) {
841 return Stage1ZirInstIdResetResult;
842}
843
844static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSetAlignStack *) {
845 return Stage1ZirInstIdSetAlignStack;
846}
847
848static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstExport *) {
849 return Stage1ZirInstIdExport;
850}
851
852static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstExtern *) {
853 return Stage1ZirInstIdExtern;
854}
855
856static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstErrorReturnTrace *) {
857 return Stage1ZirInstIdErrorReturnTrace;
858}
859
860static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstErrorUnion *) {
861 return Stage1ZirInstIdErrorUnion;
862}
863
864static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAtomicRmw *) {
865 return Stage1ZirInstIdAtomicRmw;
866}
867
868static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAtomicLoad *) {
869 return Stage1ZirInstIdAtomicLoad;
870}
871
872static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAtomicStore *) {
873 return Stage1ZirInstIdAtomicStore;
874}
875
876static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSaveErrRetAddr *) {
877 return Stage1ZirInstIdSaveErrRetAddr;
878}
879
880static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAddImplicitReturnType *) {
881 return Stage1ZirInstIdAddImplicitReturnType;
882}
883
884static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstErrSetCast *) {
885 return Stage1ZirInstIdErrSetCast;
886}
887
888static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCheckRuntimeScope *) {
889 return Stage1ZirInstIdCheckRuntimeScope;
890}
891
892static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstHasDecl *) {
893 return Stage1ZirInstIdHasDecl;
894}
895
896static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstUndeclaredIdent *) {
897 return Stage1ZirInstIdUndeclaredIdent;
898}
899
900static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAlloca *) {
901 return Stage1ZirInstIdAlloca;
902}
903
904static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstEndExpr *) {
905 return Stage1ZirInstIdEndExpr;
906}
907
908static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstUnionInitNamedField *) {
909 return Stage1ZirInstIdUnionInitNamedField;
910}
911
912static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSuspendBegin *) {
913 return Stage1ZirInstIdSuspendBegin;
914}
915
916static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSuspendFinish *) {
917 return Stage1ZirInstIdSuspendFinish;
918}
919
920static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAwait *) {
921 return Stage1ZirInstIdAwait;
922}
923
924static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstResume *) {
925 return Stage1ZirInstIdResume;
926}
927
928static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSpillBegin *) {
929 return Stage1ZirInstIdSpillBegin;
930}
931
932static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSpillEnd *) {
933 return Stage1ZirInstIdSpillEnd;
934}
935
936static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstWasmMemorySize *) {
937 return Stage1ZirInstIdWasmMemorySize;
938}
939
940static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstWasmMemoryGrow *) {
941 return Stage1ZirInstIdWasmMemoryGrow;
942}
943
944static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSrc *) {
945 return Stage1ZirInstIdSrc;
946}
947
948static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPrefetch *) {
949 return Stage1ZirInstIdPrefetch;
950}
951
952static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAddrSpaceCast *) {
953 return Stage1ZirInstIdAddrSpaceCast;
954}
955
956template<typename T>
957static T *ir_create_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
958 T *special_instruction = heap::c_allocator.create<T>();
959 special_instruction->base.id = ir_inst_id(special_instruction);
960 special_instruction->base.scope = scope;
961 special_instruction->base.source_node = source_node;
962 special_instruction->base.debug_id = irb_next_debug_id(ag);
963 special_instruction->base.owner_bb = ag->current_basic_block;
964 return special_instruction;
965}
966
967template<typename T>
968static T *ir_build_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
969 T *special_instruction = ir_create_instruction<T>(ag, scope, source_node);
970 ir_instruction_append(ag->current_basic_block, &special_instruction->base);
971 return special_instruction;
972}
973
974static Stage1ZirInst *ir_build_cond_br(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *condition,
975 Stage1ZirBasicBlock *then_block, Stage1ZirBasicBlock *else_block, Stage1ZirInst *is_comptime)
976{
977 Stage1ZirInstCondBr *inst = ir_build_instruction<Stage1ZirInstCondBr>(ag, scope, source_node);
978 inst->condition = condition;
979 inst->then_block = then_block;
980 inst->else_block = else_block;
981 inst->is_comptime = is_comptime;
982
983 ir_ref_instruction(condition, ag->current_basic_block);
984 ir_ref_bb(then_block);
985 ir_ref_bb(else_block);
986 if (is_comptime != nullptr) ir_ref_instruction(is_comptime, ag->current_basic_block);
987
988 return &inst->base;
989}
990
991static Stage1ZirInst *ir_build_return_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *operand) {
992 Stage1ZirInstReturn *inst = ir_build_instruction<Stage1ZirInstReturn>(ag, scope, source_node);
993 inst->operand = operand;
994
995 if (operand != nullptr) ir_ref_instruction(operand, ag->current_basic_block);
996
997 return &inst->base;
998}
999
1000static Stage1ZirInst *ir_build_const_void(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
1001 Stage1ZirInstConst *const_instruction = ir_create_instruction<Stage1ZirInstConst>(ag, scope, source_node);
1002 ir_instruction_append(ag->current_basic_block, &const_instruction->base);
1003 const_instruction->value = ag->codegen->intern.for_void();
1004 return &const_instruction->base;
1005}
1006
1007static Stage1ZirInst *ir_build_const_undefined(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
1008 Stage1ZirInstConst *const_instruction = ir_create_instruction<Stage1ZirInstConst>(ag, scope, source_node);
1009 ir_instruction_append(ag->current_basic_block, &const_instruction->base);
1010 const_instruction->value = ag->codegen->intern.for_undefined();
1011 const_instruction->value->special = ConstValSpecialUndef;
1012 return &const_instruction->base;
1013}
1014
1015static Stage1ZirInst *ir_build_const_uint(Stage1AstGen *ag, Scope *scope, AstNode *source_node, uint64_t value) {
1016 Stage1ZirInstConst *const_instruction = ir_build_instruction<Stage1ZirInstConst>(ag, scope, source_node);
1017 const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>();
1018 const_instruction->value->type = ag->codegen->builtin_types.entry_num_lit_int;
1019 const_instruction->value->special = ConstValSpecialStatic;
1020 bigint_init_unsigned(&const_instruction->value->data.x_bigint, value);
1021 return &const_instruction->base;
1022}
1023
1024static Stage1ZirInst *ir_build_const_bigint(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1025 BigInt bigint)
1026{
1027 Stage1ZirInstConst *const_instruction = ir_build_instruction<Stage1ZirInstConst>(ag, scope, source_node);
1028 const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>();
1029 const_instruction->value->type = ag->codegen->builtin_types.entry_num_lit_int;
1030 const_instruction->value->special = ConstValSpecialStatic;
1031 const_instruction->value->data.x_bigint = bigint;
1032 return &const_instruction->base;
1033}
1034
1035static Stage1ZirInst *ir_build_const_bigfloat(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1036 BigFloat bigfloat)
1037{
1038 Stage1ZirInstConst *const_instruction = ir_build_instruction<Stage1ZirInstConst>(ag, scope, source_node);
1039 const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>();
1040 const_instruction->value->type = ag->codegen->builtin_types.entry_num_lit_float;
1041 const_instruction->value->special = ConstValSpecialStatic;
1042 const_instruction->value->data.x_bigfloat = bigfloat;
1043 return &const_instruction->base;
1044}
1045
1046static Stage1ZirInst *ir_build_const_null(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
1047 Stage1ZirInstConst *const_instruction = ir_create_instruction<Stage1ZirInstConst>(ag, scope, source_node);
1048 ir_instruction_append(ag->current_basic_block, &const_instruction->base);
1049 const_instruction->value = ag->codegen->intern.for_null();
1050 return &const_instruction->base;
1051}
1052
1053static Stage1ZirInst *ir_build_const_usize(Stage1AstGen *ag, Scope *scope, AstNode *source_node, uint64_t value) {
1054 Stage1ZirInstConst *const_instruction = ir_build_instruction<Stage1ZirInstConst>(ag, scope, source_node);
1055 const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>();
1056 const_instruction->value->type = ag->codegen->builtin_types.entry_usize;
1057 const_instruction->value->special = ConstValSpecialStatic;
1058 bigint_init_unsigned(&const_instruction->value->data.x_bigint, value);
1059 return &const_instruction->base;
1060}
1061
1062static Stage1ZirInst *ir_create_const_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1063 ZigType *type_entry)
1064{
1065 Stage1ZirInstConst *const_instruction = ir_create_instruction<Stage1ZirInstConst>(ag, scope, source_node);
1066 const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>();
1067 const_instruction->value->type = ag->codegen->builtin_types.entry_type;
1068 const_instruction->value->special = ConstValSpecialStatic;
1069 const_instruction->value->data.x_type = type_entry;
1070 return &const_instruction->base;
1071}
1072
1073static Stage1ZirInst *ir_build_const_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1074 ZigType *type_entry)
1075{
1076 Stage1ZirInst *instruction = ir_create_const_type(ag, scope, source_node, type_entry);
1077 ir_instruction_append(ag->current_basic_block, instruction);
1078 return instruction;
1079}
1080
1081static Stage1ZirInst *ir_build_const_import(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigType *import) {
1082 Stage1ZirInstConst *const_instruction = ir_build_instruction<Stage1ZirInstConst>(ag, scope, source_node);
1083 const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>();
1084 const_instruction->value->type = ag->codegen->builtin_types.entry_type;
1085 const_instruction->value->special = ConstValSpecialStatic;
1086 const_instruction->value->data.x_type = import;
1087 return &const_instruction->base;
1088}
1089
1090static Stage1ZirInst *ir_build_const_bool(Stage1AstGen *ag, Scope *scope, AstNode *source_node, bool value) {
1091 Stage1ZirInstConst *const_instruction = ir_build_instruction<Stage1ZirInstConst>(ag, scope, source_node);
1092 const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>();
1093 const_instruction->value->type = ag->codegen->builtin_types.entry_bool;
1094 const_instruction->value->special = ConstValSpecialStatic;
1095 const_instruction->value->data.x_bool = value;
1096 return &const_instruction->base;
1097}
1098
1099static Stage1ZirInst *ir_build_const_enum_literal(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Buf *name) {
1100 Stage1ZirInstConst *const_instruction = ir_build_instruction<Stage1ZirInstConst>(ag, scope, source_node);
1101 const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>();
1102 const_instruction->value->type = ag->codegen->builtin_types.entry_enum_literal;
1103 const_instruction->value->special = ConstValSpecialStatic;
1104 const_instruction->value->data.x_enum_literal = name;
1105 return &const_instruction->base;
1106}
1107
1108// Consumes `str`.
1109static Stage1ZirInst *ir_create_const_str_lit(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Buf *str) {
1110 Stage1ZirInstConst *const_instruction = ir_create_instruction<Stage1ZirInstConst>(ag, scope, source_node);
1111 const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>();
1112 init_const_str_lit(ag->codegen, const_instruction->value, str, true);
1113
1114 return &const_instruction->base;
1115}
1116
1117// Consumes `str`.
1118static Stage1ZirInst *ir_build_const_str_lit(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Buf *str) {
1119 Stage1ZirInst *instruction = ir_create_const_str_lit(ag, scope, source_node, str);
1120 ir_instruction_append(ag->current_basic_block, instruction);
1121 return instruction;
1122}
1123
1124static Stage1ZirInst *ir_build_bin_op(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrBinOp op_id,
1125 Stage1ZirInst *op1, Stage1ZirInst *op2, bool safety_check_on)
1126{
1127 Stage1ZirInstBinOp *inst = ir_build_instruction<Stage1ZirInstBinOp>(ag, scope, source_node);
1128 inst->op_id = op_id;
1129 inst->op1 = op1;
1130 inst->op2 = op2;
1131 inst->safety_check_on = safety_check_on;
1132
1133 ir_ref_instruction(op1, ag->current_basic_block);
1134 ir_ref_instruction(op2, ag->current_basic_block);
1135
1136 return &inst->base;
1137}
1138
1139static Stage1ZirInst *ir_build_merge_err_sets(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1140 Stage1ZirInst *op1, Stage1ZirInst *op2, Buf *type_name)
1141{
1142 Stage1ZirInstMergeErrSets *inst = ir_build_instruction<Stage1ZirInstMergeErrSets>(ag, scope, source_node);
1143 inst->op1 = op1;
1144 inst->op2 = op2;
1145 inst->type_name = type_name;
1146
1147 ir_ref_instruction(op1, ag->current_basic_block);
1148 ir_ref_instruction(op2, ag->current_basic_block);
1149
1150 return &inst->base;
1151}
1152
1153static Stage1ZirInst *ir_build_var_ptr_x(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigVar *var,
1154 ScopeFnDef *crossed_fndef_scope)
1155{
1156 Stage1ZirInstVarPtr *instruction = ir_build_instruction<Stage1ZirInstVarPtr>(ag, scope, source_node);
1157 instruction->var = var;
1158 instruction->crossed_fndef_scope = crossed_fndef_scope;
1159
1160 var->ref_count += 1;
1161
1162 return &instruction->base;
1163}
1164
1165static Stage1ZirInst *ir_build_var_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigVar *var) {
1166 return ir_build_var_ptr_x(ag, scope, source_node, var, nullptr);
1167}
1168
1169static Stage1ZirInst *ir_build_elem_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1170 Stage1ZirInst *array_ptr, Stage1ZirInst *elem_index, bool safety_check_on, PtrLen ptr_len,
1171 AstNode *init_array_type_source_node)
1172{
1173 Stage1ZirInstElemPtr *instruction = ir_build_instruction<Stage1ZirInstElemPtr>(ag, scope, source_node);
1174 instruction->array_ptr = array_ptr;
1175 instruction->elem_index = elem_index;
1176 instruction->safety_check_on = safety_check_on;
1177 instruction->ptr_len = ptr_len;
1178 instruction->init_array_type_source_node = init_array_type_source_node;
1179
1180 ir_ref_instruction(array_ptr, ag->current_basic_block);
1181 ir_ref_instruction(elem_index, ag->current_basic_block);
1182
1183 return &instruction->base;
1184}
1185
1186static Stage1ZirInst *ir_build_field_ptr_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1187 Stage1ZirInst *container_ptr, Stage1ZirInst *field_name_expr, bool initializing)
1188{
1189 Stage1ZirInstFieldPtr *instruction = ir_build_instruction<Stage1ZirInstFieldPtr>(ag, scope, source_node);
1190 instruction->container_ptr = container_ptr;
1191 instruction->field_name_buffer = nullptr;
1192 instruction->field_name_expr = field_name_expr;
1193 instruction->initializing = initializing;
1194
1195 ir_ref_instruction(container_ptr, ag->current_basic_block);
1196 ir_ref_instruction(field_name_expr, ag->current_basic_block);
1197
1198 return &instruction->base;
1199}
1200
1201static Stage1ZirInst *ir_build_field_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1202 Stage1ZirInst *container_ptr, Buf *field_name, bool initializing)
1203{
1204 Stage1ZirInstFieldPtr *instruction = ir_build_instruction<Stage1ZirInstFieldPtr>(ag, scope, source_node);
1205 instruction->container_ptr = container_ptr;
1206 instruction->field_name_buffer = field_name;
1207 instruction->field_name_expr = nullptr;
1208 instruction->initializing = initializing;
1209
1210 ir_ref_instruction(container_ptr, ag->current_basic_block);
1211
1212 return &instruction->base;
1213}
1214
1215static Stage1ZirInst *ir_build_has_field(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1216 Stage1ZirInst *container_type, Stage1ZirInst *field_name)
1217{
1218 Stage1ZirInstHasField *instruction = ir_build_instruction<Stage1ZirInstHasField>(ag, scope, source_node);
1219 instruction->container_type = container_type;
1220 instruction->field_name = field_name;
1221
1222 ir_ref_instruction(container_type, ag->current_basic_block);
1223 ir_ref_instruction(field_name, ag->current_basic_block);
1224
1225 return &instruction->base;
1226}
1227
1228static Stage1ZirInst *ir_build_call_extra(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1229 Stage1ZirInst *options, Stage1ZirInst *fn_ref, Stage1ZirInst *args, ResultLoc *result_loc)
1230{
1231 Stage1ZirInstCallExtra *call_instruction = ir_build_instruction<Stage1ZirInstCallExtra>(ag, scope, source_node);
1232 call_instruction->options = options;
1233 call_instruction->fn_ref = fn_ref;
1234 call_instruction->args = args;
1235 call_instruction->result_loc = result_loc;
1236
1237 ir_ref_instruction(options, ag->current_basic_block);
1238 ir_ref_instruction(fn_ref, ag->current_basic_block);
1239 ir_ref_instruction(args, ag->current_basic_block);
1240
1241 return &call_instruction->base;
1242}
1243
1244static Stage1ZirInst *ir_build_async_call_extra(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1245 CallModifier modifier, Stage1ZirInst *fn_ref, Stage1ZirInst *ret_ptr, Stage1ZirInst *new_stack, Stage1ZirInst *args, ResultLoc *result_loc)
1246{
1247 Stage1ZirInstAsyncCallExtra *call_instruction = ir_build_instruction<Stage1ZirInstAsyncCallExtra>(ag, scope, source_node);
1248 call_instruction->modifier = modifier;
1249 call_instruction->fn_ref = fn_ref;
1250 call_instruction->ret_ptr = ret_ptr;
1251 call_instruction->new_stack = new_stack;
1252 call_instruction->args = args;
1253 call_instruction->result_loc = result_loc;
1254
1255 ir_ref_instruction(fn_ref, ag->current_basic_block);
1256 if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, ag->current_basic_block);
1257 ir_ref_instruction(new_stack, ag->current_basic_block);
1258 ir_ref_instruction(args, ag->current_basic_block);
1259
1260 return &call_instruction->base;
1261}
1262
1263static Stage1ZirInst *ir_build_call_args(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1264 Stage1ZirInst *options, Stage1ZirInst *fn_ref, Stage1ZirInst **args_ptr, size_t args_len,
1265 ResultLoc *result_loc)
1266{
1267 Stage1ZirInstCallArgs *call_instruction = ir_build_instruction<Stage1ZirInstCallArgs>(ag, scope, source_node);
1268 call_instruction->options = options;
1269 call_instruction->fn_ref = fn_ref;
1270 call_instruction->args_ptr = args_ptr;
1271 call_instruction->args_len = args_len;
1272 call_instruction->result_loc = result_loc;
1273
1274 ir_ref_instruction(options, ag->current_basic_block);
1275 ir_ref_instruction(fn_ref, ag->current_basic_block);
1276 for (size_t i = 0; i < args_len; i += 1)
1277 ir_ref_instruction(args_ptr[i], ag->current_basic_block);
1278
1279 return &call_instruction->base;
1280}
1281
1282static Stage1ZirInst *ir_build_call_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1283 ZigFn *fn_entry, Stage1ZirInst *fn_ref, size_t arg_count, Stage1ZirInst **args,
1284 Stage1ZirInst *ret_ptr, CallModifier modifier, bool is_async_call_builtin,
1285 Stage1ZirInst *new_stack, ResultLoc *result_loc)
1286{
1287 Stage1ZirInstCall *call_instruction = ir_build_instruction<Stage1ZirInstCall>(ag, scope, source_node);
1288 call_instruction->fn_entry = fn_entry;
1289 call_instruction->fn_ref = fn_ref;
1290 call_instruction->args = args;
1291 call_instruction->arg_count = arg_count;
1292 call_instruction->modifier = modifier;
1293 call_instruction->is_async_call_builtin = is_async_call_builtin;
1294 call_instruction->new_stack = new_stack;
1295 call_instruction->result_loc = result_loc;
1296 call_instruction->ret_ptr = ret_ptr;
1297
1298 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, ag->current_basic_block);
1299 for (size_t i = 0; i < arg_count; i += 1)
1300 ir_ref_instruction(args[i], ag->current_basic_block);
1301 if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, ag->current_basic_block);
1302 if (new_stack != nullptr) ir_ref_instruction(new_stack, ag->current_basic_block);
1303
1304 return &call_instruction->base;
1305}
1306
1307static Stage1ZirInst *ir_build_phi(Stage1AstGen *ag, Scope *scope, AstNode *source_node, bool merge_comptime,
1308 size_t incoming_count, Stage1ZirBasicBlock **incoming_blocks, Stage1ZirInst **incoming_values,
1309 ResultLocPeerParent *peer_parent)
1310{
1311 assert(incoming_count != 0);
1312 assert(incoming_count != SIZE_MAX);
1313
1314 Stage1ZirInstPhi *phi_instruction = ir_build_instruction<Stage1ZirInstPhi>(ag, scope, source_node);
1315 phi_instruction->incoming_count = incoming_count;
1316 phi_instruction->incoming_blocks = incoming_blocks;
1317 phi_instruction->incoming_values = incoming_values;
1318 phi_instruction->peer_parent = peer_parent;
1319 phi_instruction->merge_comptime = merge_comptime;
1320
1321 for (size_t i = 0; i < incoming_count; i += 1) {
1322 ir_ref_bb(incoming_blocks[i]);
1323 ir_ref_instruction(incoming_values[i], ag->current_basic_block);
1324 }
1325
1326 return &phi_instruction->base;
1327}
1328
1329static Stage1ZirInst *ir_build_br(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1330 Stage1ZirBasicBlock *dest_block, Stage1ZirInst *is_comptime)
1331{
1332 Stage1ZirInstBr *inst = ir_build_instruction<Stage1ZirInstBr>(ag, scope, source_node);
1333 inst->dest_block = dest_block;
1334 inst->is_comptime = is_comptime;
1335
1336 ir_ref_bb(dest_block);
1337 if (is_comptime) ir_ref_instruction(is_comptime, ag->current_basic_block);
1338
1339 return &inst->base;
1340}
1341
1342static Stage1ZirInst *ir_build_ptr_type_simple(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1343 Stage1ZirInst *child_type, bool is_const)
1344{
1345 Stage1ZirInstPtrTypeSimple *inst = heap::c_allocator.create<Stage1ZirInstPtrTypeSimple>();
1346 inst->base.id = is_const ? Stage1ZirInstIdPtrTypeSimpleConst : Stage1ZirInstIdPtrTypeSimple;
1347 inst->base.scope = scope;
1348 inst->base.source_node = source_node;
1349 inst->base.debug_id = irb_next_debug_id(ag);
1350 inst->base.owner_bb = ag->current_basic_block;
1351 ir_instruction_append(ag->current_basic_block, &inst->base);
1352
1353 inst->child_type = child_type;
1354
1355 ir_ref_instruction(child_type, ag->current_basic_block);
1356
1357 return &inst->base;
1358}
1359
1360static Stage1ZirInst *ir_build_ptr_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1361 Stage1ZirInst *child_type, bool is_const, bool is_volatile, PtrLen ptr_len,
1362 Stage1ZirInst *sentinel, Stage1ZirInst *align_value,
1363 uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero)
1364{
1365 if (!is_volatile && ptr_len == PtrLenSingle && sentinel == nullptr && align_value == nullptr &&
1366 bit_offset_start == 0 && host_int_bytes == 0 && is_allow_zero == 0)
1367 {
1368 return ir_build_ptr_type_simple(ag, scope, source_node, child_type, is_const);
1369 }
1370
1371 Stage1ZirInstPtrType *inst = ir_build_instruction<Stage1ZirInstPtrType>(ag, scope, source_node);
1372 inst->sentinel = sentinel;
1373 inst->align_value = align_value;
1374 inst->child_type = child_type;
1375 inst->is_const = is_const;
1376 inst->is_volatile = is_volatile;
1377 inst->ptr_len = ptr_len;
1378 inst->bit_offset_start = bit_offset_start;
1379 inst->host_int_bytes = host_int_bytes;
1380 inst->is_allow_zero = is_allow_zero;
1381
1382 if (sentinel) ir_ref_instruction(sentinel, ag->current_basic_block);
1383 if (align_value) ir_ref_instruction(align_value, ag->current_basic_block);
1384 ir_ref_instruction(child_type, ag->current_basic_block);
1385
1386 return &inst->base;
1387}
1388
1389static Stage1ZirInst *ir_build_un_op_lval(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrUnOp op_id,
1390 Stage1ZirInst *value, LVal lval, ResultLoc *result_loc)
1391{
1392 Stage1ZirInstUnOp *instruction = ir_build_instruction<Stage1ZirInstUnOp>(ag, scope, source_node);
1393 instruction->op_id = op_id;
1394 instruction->value = value;
1395 instruction->lval = lval;
1396 instruction->result_loc = result_loc;
1397
1398 ir_ref_instruction(value, ag->current_basic_block);
1399
1400 return &instruction->base;
1401}
1402
1403static Stage1ZirInst *ir_build_un_op(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrUnOp op_id,
1404 Stage1ZirInst *value)
1405{
1406 return ir_build_un_op_lval(ag, scope, source_node, op_id, value, LValNone, nullptr);
1407}
1408
1409static Stage1ZirInst *ir_build_container_init_list(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1410 size_t item_count, Stage1ZirInst **elem_result_loc_list, Stage1ZirInst *result_loc,
1411 AstNode *init_array_type_source_node)
1412{
1413 Stage1ZirInstContainerInitList *container_init_list_instruction =
1414 ir_build_instruction<Stage1ZirInstContainerInitList>(ag, scope, source_node);
1415 container_init_list_instruction->item_count = item_count;
1416 container_init_list_instruction->elem_result_loc_list = elem_result_loc_list;
1417 container_init_list_instruction->result_loc = result_loc;
1418 container_init_list_instruction->init_array_type_source_node = init_array_type_source_node;
1419
1420 for (size_t i = 0; i < item_count; i += 1) {
1421 ir_ref_instruction(elem_result_loc_list[i], ag->current_basic_block);
1422 }
1423 if (result_loc != nullptr) ir_ref_instruction(result_loc, ag->current_basic_block);
1424
1425 return &container_init_list_instruction->base;
1426}
1427
1428static Stage1ZirInst *ir_build_container_init_fields(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1429 size_t field_count, Stage1ZirInstContainerInitFieldsField *fields, Stage1ZirInst *result_loc)
1430{
1431 Stage1ZirInstContainerInitFields *container_init_fields_instruction =
1432 ir_build_instruction<Stage1ZirInstContainerInitFields>(ag, scope, source_node);
1433 container_init_fields_instruction->field_count = field_count;
1434 container_init_fields_instruction->fields = fields;
1435 container_init_fields_instruction->result_loc = result_loc;
1436
1437 for (size_t i = 0; i < field_count; i += 1) {
1438 ir_ref_instruction(fields[i].result_loc, ag->current_basic_block);
1439 }
1440 if (result_loc != nullptr) ir_ref_instruction(result_loc, ag->current_basic_block);
1441
1442 return &container_init_fields_instruction->base;
1443}
1444
1445static Stage1ZirInst *ir_build_unreachable(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
1446 Stage1ZirInstUnreachable *inst = ir_build_instruction<Stage1ZirInstUnreachable>(ag, scope, source_node);
1447 return &inst->base;
1448}
1449
1450static Stage1ZirInstStorePtr *ir_build_store_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1451 Stage1ZirInst *ptr, Stage1ZirInst *value)
1452{
1453 Stage1ZirInstStorePtr *instruction = ir_build_instruction<Stage1ZirInstStorePtr>(ag, scope, source_node);
1454 instruction->ptr = ptr;
1455 instruction->value = value;
1456
1457 ir_ref_instruction(ptr, ag->current_basic_block);
1458 ir_ref_instruction(value, ag->current_basic_block);
1459
1460 return instruction;
1461}
1462
1463static Stage1ZirInst *ir_build_var_decl_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1464 ZigVar *var, Stage1ZirInst *align_value, Stage1ZirInst *ptr)
1465{
1466 Stage1ZirInstDeclVar *inst = ir_build_instruction<Stage1ZirInstDeclVar>(ag, scope, source_node);
1467 inst->var = var;
1468 inst->align_value = align_value;
1469 inst->ptr = ptr;
1470
1471 if (align_value != nullptr) ir_ref_instruction(align_value, ag->current_basic_block);
1472 ir_ref_instruction(ptr, ag->current_basic_block);
1473
1474 return &inst->base;
1475}
1476
1477static Stage1ZirInst *ir_build_export(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1478 Stage1ZirInst *target, Stage1ZirInst *options)
1479{
1480 Stage1ZirInstExport *export_instruction = ir_build_instruction<Stage1ZirInstExport>(
1481 ag, scope, source_node);
1482 export_instruction->target = target;
1483 export_instruction->options = options;
1484
1485 ir_ref_instruction(target, ag->current_basic_block);
1486 ir_ref_instruction(options, ag->current_basic_block);
1487
1488 return &export_instruction->base;
1489}
1490
1491static Stage1ZirInst *ir_build_extern(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1492 Stage1ZirInst *type, Stage1ZirInst *options)
1493{
1494 Stage1ZirInstExtern *extern_instruction = ir_build_instruction<Stage1ZirInstExtern>(
1495 ag, scope, source_node);
1496 extern_instruction->type = type;
1497 extern_instruction->options = options;
1498
1499 ir_ref_instruction(type, ag->current_basic_block);
1500 ir_ref_instruction(options, ag->current_basic_block);
1501
1502 return &extern_instruction->base;
1503}
1504
1505static Stage1ZirInst *ir_build_load_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *ptr) {
1506 Stage1ZirInstLoadPtr *instruction = ir_build_instruction<Stage1ZirInstLoadPtr>(ag, scope, source_node);
1507 instruction->ptr = ptr;
1508
1509 ir_ref_instruction(ptr, ag->current_basic_block);
1510
1511 return &instruction->base;
1512}
1513
1514static Stage1ZirInst *ir_build_typeof_n(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1515 Stage1ZirInst **values, size_t value_count)
1516{
1517 assert(value_count >= 2);
1518
1519 Stage1ZirInstTypeOf *instruction = ir_build_instruction<Stage1ZirInstTypeOf>(ag, scope, source_node);
1520 instruction->value.list = values;
1521 instruction->value_count = value_count;
1522
1523 for (size_t i = 0; i < value_count; i++)
1524 ir_ref_instruction(values[i], ag->current_basic_block);
1525
1526 return &instruction->base;
1527}
1528
1529static Stage1ZirInst *ir_build_typeof_1(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *value) {
1530 Stage1ZirInstTypeOf *instruction = ir_build_instruction<Stage1ZirInstTypeOf>(ag, scope, source_node);
1531 instruction->value.scalar = value;
1532
1533 ir_ref_instruction(value, ag->current_basic_block);
1534
1535 return &instruction->base;
1536}
1537
1538static Stage1ZirInst *ir_build_set_cold(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *is_cold) {
1539 Stage1ZirInstSetCold *instruction = ir_build_instruction<Stage1ZirInstSetCold>(ag, scope, source_node);
1540 instruction->is_cold = is_cold;
1541
1542 ir_ref_instruction(is_cold, ag->current_basic_block);
1543
1544 return &instruction->base;
1545}
1546
1547static Stage1ZirInst *ir_build_set_runtime_safety(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1548 Stage1ZirInst *safety_on)
1549{
1550 Stage1ZirInstSetRuntimeSafety *inst = ir_build_instruction<Stage1ZirInstSetRuntimeSafety>(ag, scope, source_node);
1551 inst->safety_on = safety_on;
1552
1553 ir_ref_instruction(safety_on, ag->current_basic_block);
1554
1555 return &inst->base;
1556}
1557
1558static Stage1ZirInst *ir_build_set_float_mode(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1559 Stage1ZirInst *mode_value)
1560{
1561 Stage1ZirInstSetFloatMode *instruction = ir_build_instruction<Stage1ZirInstSetFloatMode>(ag, scope, source_node);
1562 instruction->mode_value = mode_value;
1563
1564 ir_ref_instruction(mode_value, ag->current_basic_block);
1565
1566 return &instruction->base;
1567}
1568
1569static Stage1ZirInst *ir_build_array_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *size,
1570 Stage1ZirInst *sentinel, Stage1ZirInst *child_type)
1571{
1572 Stage1ZirInstArrayType *instruction = ir_build_instruction<Stage1ZirInstArrayType>(ag, scope, source_node);
1573 instruction->size = size;
1574 instruction->sentinel = sentinel;
1575 instruction->child_type = child_type;
1576
1577 ir_ref_instruction(size, ag->current_basic_block);
1578 if (sentinel != nullptr) ir_ref_instruction(sentinel, ag->current_basic_block);
1579 ir_ref_instruction(child_type, ag->current_basic_block);
1580
1581 return &instruction->base;
1582}
1583
1584static Stage1ZirInst *ir_build_anyframe_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1585 Stage1ZirInst *payload_type)
1586{
1587 Stage1ZirInstAnyFrameType *instruction = ir_build_instruction<Stage1ZirInstAnyFrameType>(ag, scope, source_node);
1588 instruction->payload_type = payload_type;
1589
1590 if (payload_type != nullptr) ir_ref_instruction(payload_type, ag->current_basic_block);
1591
1592 return &instruction->base;
1593}
1594
1595static Stage1ZirInst *ir_build_slice_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1596 Stage1ZirInst *child_type, bool is_const, bool is_volatile,
1597 Stage1ZirInst *sentinel, Stage1ZirInst *align_value, bool is_allow_zero)
1598{
1599 Stage1ZirInstSliceType *instruction = ir_build_instruction<Stage1ZirInstSliceType>(ag, scope, source_node);
1600 instruction->is_const = is_const;
1601 instruction->is_volatile = is_volatile;
1602 instruction->child_type = child_type;
1603 instruction->sentinel = sentinel;
1604 instruction->align_value = align_value;
1605 instruction->is_allow_zero = is_allow_zero;
1606
1607 if (sentinel != nullptr) ir_ref_instruction(sentinel, ag->current_basic_block);
1608 if (align_value != nullptr) ir_ref_instruction(align_value, ag->current_basic_block);
1609 ir_ref_instruction(child_type, ag->current_basic_block);
1610
1611 return &instruction->base;
1612}
1613
1614static Stage1ZirInst *ir_build_asm_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1615 Stage1ZirInst *asm_template, Stage1ZirInst **input_list, Stage1ZirInst **output_types,
1616 ZigVar **output_vars, size_t return_count, bool has_side_effects, bool is_global)
1617{
1618 Stage1ZirInstAsm *instruction = ir_build_instruction<Stage1ZirInstAsm>(ag, scope, source_node);
1619 instruction->asm_template = asm_template;
1620 instruction->input_list = input_list;
1621 instruction->output_types = output_types;
1622 instruction->output_vars = output_vars;
1623 instruction->return_count = return_count;
1624 instruction->has_side_effects = has_side_effects;
1625 instruction->is_global = is_global;
1626
1627 assert(source_node->type == NodeTypeAsmExpr);
1628 for (size_t i = 0; i < source_node->data.asm_expr.output_list.length; i += 1) {
1629 Stage1ZirInst *output_type = output_types[i];
1630 if (output_type) ir_ref_instruction(output_type, ag->current_basic_block);
1631 }
1632
1633 for (size_t i = 0; i < source_node->data.asm_expr.input_list.length; i += 1) {
1634 Stage1ZirInst *input_value = input_list[i];
1635 ir_ref_instruction(input_value, ag->current_basic_block);
1636 }
1637
1638 return &instruction->base;
1639}
1640
1641static Stage1ZirInst *ir_build_size_of(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *type_value,
1642 bool bit_size)
1643{
1644 Stage1ZirInstSizeOf *instruction = ir_build_instruction<Stage1ZirInstSizeOf>(ag, scope, source_node);
1645 instruction->type_value = type_value;
1646 instruction->bit_size = bit_size;
1647
1648 ir_ref_instruction(type_value, ag->current_basic_block);
1649
1650 return &instruction->base;
1651}
1652
1653static Stage1ZirInst *ir_build_test_non_null_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1654 Stage1ZirInst *value)
1655{
1656 Stage1ZirInstTestNonNull *instruction = ir_build_instruction<Stage1ZirInstTestNonNull>(ag, scope, source_node);
1657 instruction->value = value;
1658
1659 ir_ref_instruction(value, ag->current_basic_block);
1660
1661 return &instruction->base;
1662}
1663
1664static Stage1ZirInst *ir_build_optional_unwrap_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1665 Stage1ZirInst *base_ptr, bool safety_check_on)
1666{
1667 Stage1ZirInstOptionalUnwrapPtr *instruction = ir_build_instruction<Stage1ZirInstOptionalUnwrapPtr>(ag, scope, source_node);
1668 instruction->base_ptr = base_ptr;
1669 instruction->safety_check_on = safety_check_on;
1670
1671 ir_ref_instruction(base_ptr, ag->current_basic_block);
1672
1673 return &instruction->base;
1674}
1675
1676static Stage1ZirInst *ir_build_clz(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *type,
1677 Stage1ZirInst *op)
1678{
1679 Stage1ZirInstClz *instruction = ir_build_instruction<Stage1ZirInstClz>(ag, scope, source_node);
1680 instruction->type = type;
1681 instruction->op = op;
1682
1683 ir_ref_instruction(type, ag->current_basic_block);
1684 ir_ref_instruction(op, ag->current_basic_block);
1685
1686 return &instruction->base;
1687}
1688
1689static Stage1ZirInst *ir_build_ctz(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *type,
1690 Stage1ZirInst *op)
1691{
1692 Stage1ZirInstCtz *instruction = ir_build_instruction<Stage1ZirInstCtz>(ag, scope, source_node);
1693 instruction->type = type;
1694 instruction->op = op;
1695
1696 ir_ref_instruction(type, ag->current_basic_block);
1697 ir_ref_instruction(op, ag->current_basic_block);
1698
1699 return &instruction->base;
1700}
1701
1702static Stage1ZirInst *ir_build_pop_count(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *type,
1703 Stage1ZirInst *op)
1704{
1705 Stage1ZirInstPopCount *instruction = ir_build_instruction<Stage1ZirInstPopCount>(ag, scope, source_node);
1706 instruction->type = type;
1707 instruction->op = op;
1708
1709 ir_ref_instruction(type, ag->current_basic_block);
1710 ir_ref_instruction(op, ag->current_basic_block);
1711
1712 return &instruction->base;
1713}
1714
1715static Stage1ZirInst *ir_build_bswap(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *type,
1716 Stage1ZirInst *op)
1717{
1718 Stage1ZirInstBswap *instruction = ir_build_instruction<Stage1ZirInstBswap>(ag, scope, source_node);
1719 instruction->type = type;
1720 instruction->op = op;
1721
1722 ir_ref_instruction(type, ag->current_basic_block);
1723 ir_ref_instruction(op, ag->current_basic_block);
1724
1725 return &instruction->base;
1726}
1727
1728static Stage1ZirInst *ir_build_bit_reverse(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *type,
1729 Stage1ZirInst *op)
1730{
1731 Stage1ZirInstBitReverse *instruction = ir_build_instruction<Stage1ZirInstBitReverse>(ag, scope, source_node);
1732 instruction->type = type;
1733 instruction->op = op;
1734
1735 ir_ref_instruction(type, ag->current_basic_block);
1736 ir_ref_instruction(op, ag->current_basic_block);
1737
1738 return &instruction->base;
1739}
1740
1741static Stage1ZirInstSwitchBr *ir_build_switch_br_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1742 Stage1ZirInst *target_value, Stage1ZirBasicBlock *else_block, size_t case_count, Stage1ZirInstSwitchBrCase *cases,
1743 Stage1ZirInst *is_comptime, Stage1ZirInst *switch_prongs_void)
1744{
1745 Stage1ZirInstSwitchBr *instruction = ir_build_instruction<Stage1ZirInstSwitchBr>(ag, scope, source_node);
1746 instruction->target_value = target_value;
1747 instruction->else_block = else_block;
1748 instruction->case_count = case_count;
1749 instruction->cases = cases;
1750 instruction->is_comptime = is_comptime;
1751 instruction->switch_prongs_void = switch_prongs_void;
1752
1753 ir_ref_instruction(target_value, ag->current_basic_block);
1754 ir_ref_instruction(is_comptime, ag->current_basic_block);
1755 ir_ref_bb(else_block);
1756 ir_ref_instruction(switch_prongs_void, ag->current_basic_block);
1757
1758 for (size_t i = 0; i < case_count; i += 1) {
1759 ir_ref_instruction(cases[i].value, ag->current_basic_block);
1760 ir_ref_bb(cases[i].block);
1761 }
1762
1763 return instruction;
1764}
1765
1766static Stage1ZirInst *ir_build_switch_target(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1767 Stage1ZirInst *target_value_ptr)
1768{
1769 Stage1ZirInstSwitchTarget *instruction = ir_build_instruction<Stage1ZirInstSwitchTarget>(ag, scope, source_node);
1770 instruction->target_value_ptr = target_value_ptr;
1771
1772 ir_ref_instruction(target_value_ptr, ag->current_basic_block);
1773
1774 return &instruction->base;
1775}
1776
1777static Stage1ZirInst *ir_build_switch_var(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1778 Stage1ZirInst *target_value_ptr, Stage1ZirInst **prongs_ptr, size_t prongs_len)
1779{
1780 Stage1ZirInstSwitchVar *instruction = ir_build_instruction<Stage1ZirInstSwitchVar>(ag, scope, source_node);
1781 instruction->target_value_ptr = target_value_ptr;
1782 instruction->prongs_ptr = prongs_ptr;
1783 instruction->prongs_len = prongs_len;
1784
1785 ir_ref_instruction(target_value_ptr, ag->current_basic_block);
1786 for (size_t i = 0; i < prongs_len; i += 1) {
1787 ir_ref_instruction(prongs_ptr[i], ag->current_basic_block);
1788 }
1789
1790 return &instruction->base;
1791}
1792
1793// For this instruction the switch_br must be set later.
1794static Stage1ZirInstSwitchElseVar *ir_build_switch_else_var(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1795 Stage1ZirInst *target_value_ptr)
1796{
1797 Stage1ZirInstSwitchElseVar *instruction = ir_build_instruction<Stage1ZirInstSwitchElseVar>(ag, scope, source_node);
1798 instruction->target_value_ptr = target_value_ptr;
1799
1800 ir_ref_instruction(target_value_ptr, ag->current_basic_block);
1801
1802 return instruction;
1803}
1804
1805static Stage1ZirInst *ir_build_import(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *name) {
1806 Stage1ZirInstImport *instruction = ir_build_instruction<Stage1ZirInstImport>(ag, scope, source_node);
1807 instruction->name = name;
1808
1809 ir_ref_instruction(name, ag->current_basic_block);
1810
1811 return &instruction->base;
1812}
1813
1814static Stage1ZirInst *ir_build_ref_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *value) {
1815 Stage1ZirInstRef *instruction = ir_build_instruction<Stage1ZirInstRef>(ag, scope, source_node);
1816 instruction->value = value;
1817
1818 ir_ref_instruction(value, ag->current_basic_block);
1819
1820 return &instruction->base;
1821}
1822
1823static Stage1ZirInst *ir_build_compile_err(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *msg) {
1824 Stage1ZirInstCompileErr *instruction = ir_build_instruction<Stage1ZirInstCompileErr>(ag, scope, source_node);
1825 instruction->msg = msg;
1826
1827 ir_ref_instruction(msg, ag->current_basic_block);
1828
1829 return &instruction->base;
1830}
1831
1832static Stage1ZirInst *ir_build_compile_log(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1833 size_t msg_count, Stage1ZirInst **msg_list)
1834{
1835 Stage1ZirInstCompileLog *instruction = ir_build_instruction<Stage1ZirInstCompileLog>(ag, scope, source_node);
1836 instruction->msg_count = msg_count;
1837 instruction->msg_list = msg_list;
1838
1839 for (size_t i = 0; i < msg_count; i += 1) {
1840 ir_ref_instruction(msg_list[i], ag->current_basic_block);
1841 }
1842
1843 return &instruction->base;
1844}
1845
1846static Stage1ZirInst *ir_build_err_name(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *value) {
1847 Stage1ZirInstErrName *instruction = ir_build_instruction<Stage1ZirInstErrName>(ag, scope, source_node);
1848 instruction->value = value;
1849
1850 ir_ref_instruction(value, ag->current_basic_block);
1851
1852 return &instruction->base;
1853}
1854
1855static Stage1ZirInst *ir_build_c_import(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
1856 Stage1ZirInstCImport *instruction = ir_build_instruction<Stage1ZirInstCImport>(ag, scope, source_node);
1857 return &instruction->base;
1858}
1859
1860static Stage1ZirInst *ir_build_c_include(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *name) {
1861 Stage1ZirInstCInclude *instruction = ir_build_instruction<Stage1ZirInstCInclude>(ag, scope, source_node);
1862 instruction->name = name;
1863
1864 ir_ref_instruction(name, ag->current_basic_block);
1865
1866 return &instruction->base;
1867}
1868
1869static Stage1ZirInst *ir_build_c_define(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *name, Stage1ZirInst *value) {
1870 Stage1ZirInstCDefine *instruction = ir_build_instruction<Stage1ZirInstCDefine>(ag, scope, source_node);
1871 instruction->name = name;
1872 instruction->value = value;
1873
1874 ir_ref_instruction(name, ag->current_basic_block);
1875 ir_ref_instruction(value, ag->current_basic_block);
1876
1877 return &instruction->base;
1878}
1879
1880static Stage1ZirInst *ir_build_c_undef(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *name) {
1881 Stage1ZirInstCUndef *instruction = ir_build_instruction<Stage1ZirInstCUndef>(ag, scope, source_node);
1882 instruction->name = name;
1883
1884 ir_ref_instruction(name, ag->current_basic_block);
1885
1886 return &instruction->base;
1887}
1888
1889static Stage1ZirInst *ir_build_embed_file(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *name) {
1890 Stage1ZirInstEmbedFile *instruction = ir_build_instruction<Stage1ZirInstEmbedFile>(ag, scope, source_node);
1891 instruction->name = name;
1892
1893 ir_ref_instruction(name, ag->current_basic_block);
1894
1895 return &instruction->base;
1896}
1897
1898static Stage1ZirInst *ir_build_cmpxchg_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1899 Stage1ZirInst *type_value, Stage1ZirInst *ptr, Stage1ZirInst *cmp_value, Stage1ZirInst *new_value,
1900 Stage1ZirInst *success_order_value, Stage1ZirInst *failure_order_value, bool is_weak, ResultLoc *result_loc)
1901{
1902 Stage1ZirInstCmpxchg *instruction = ir_build_instruction<Stage1ZirInstCmpxchg>(ag, scope, source_node);
1903 instruction->type_value = type_value;
1904 instruction->ptr = ptr;
1905 instruction->cmp_value = cmp_value;
1906 instruction->new_value = new_value;
1907 instruction->success_order_value = success_order_value;
1908 instruction->failure_order_value = failure_order_value;
1909 instruction->is_weak = is_weak;
1910 instruction->result_loc = result_loc;
1911
1912 ir_ref_instruction(type_value, ag->current_basic_block);
1913 ir_ref_instruction(ptr, ag->current_basic_block);
1914 ir_ref_instruction(cmp_value, ag->current_basic_block);
1915 ir_ref_instruction(new_value, ag->current_basic_block);
1916 ir_ref_instruction(success_order_value, ag->current_basic_block);
1917 ir_ref_instruction(failure_order_value, ag->current_basic_block);
1918
1919 return &instruction->base;
1920}
1921
1922static Stage1ZirInst *ir_build_fence(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *order) {
1923 Stage1ZirInstFence *instruction = ir_build_instruction<Stage1ZirInstFence>(ag, scope, source_node);
1924 instruction->order = order;
1925
1926 ir_ref_instruction(order, ag->current_basic_block);
1927
1928 return &instruction->base;
1929}
1930
1931static Stage1ZirInst *ir_build_reduce(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *op, Stage1ZirInst *value) {
1932 Stage1ZirInstReduce *instruction = ir_build_instruction<Stage1ZirInstReduce>(ag, scope, source_node);
1933 instruction->op = op;
1934 instruction->value = value;
1935
1936 ir_ref_instruction(op, ag->current_basic_block);
1937 ir_ref_instruction(value, ag->current_basic_block);
1938
1939 return &instruction->base;
1940}
1941
1942static Stage1ZirInst *ir_build_truncate(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1943 Stage1ZirInst *dest_type, Stage1ZirInst *target)
1944{
1945 Stage1ZirInstTruncate *instruction = ir_build_instruction<Stage1ZirInstTruncate>(ag, scope, source_node);
1946 instruction->dest_type = dest_type;
1947 instruction->target = target;
1948
1949 ir_ref_instruction(dest_type, ag->current_basic_block);
1950 ir_ref_instruction(target, ag->current_basic_block);
1951
1952 return &instruction->base;
1953}
1954
1955static Stage1ZirInst *ir_build_int_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *dest_type,
1956 Stage1ZirInst *target)
1957{
1958 Stage1ZirInstIntCast *instruction = ir_build_instruction<Stage1ZirInstIntCast>(ag, scope, source_node);
1959 instruction->dest_type = dest_type;
1960 instruction->target = target;
1961
1962 ir_ref_instruction(dest_type, ag->current_basic_block);
1963 ir_ref_instruction(target, ag->current_basic_block);
1964
1965 return &instruction->base;
1966}
1967
1968static Stage1ZirInst *ir_build_float_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *dest_type,
1969 Stage1ZirInst *target)
1970{
1971 Stage1ZirInstFloatCast *instruction = ir_build_instruction<Stage1ZirInstFloatCast>(ag, scope, source_node);
1972 instruction->dest_type = dest_type;
1973 instruction->target = target;
1974
1975 ir_ref_instruction(dest_type, ag->current_basic_block);
1976 ir_ref_instruction(target, ag->current_basic_block);
1977
1978 return &instruction->base;
1979}
1980
1981static Stage1ZirInst *ir_build_err_set_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1982 Stage1ZirInst *dest_type, Stage1ZirInst *target)
1983{
1984 Stage1ZirInstErrSetCast *instruction = ir_build_instruction<Stage1ZirInstErrSetCast>(ag, scope, source_node);
1985 instruction->dest_type = dest_type;
1986 instruction->target = target;
1987
1988 ir_ref_instruction(dest_type, ag->current_basic_block);
1989 ir_ref_instruction(target, ag->current_basic_block);
1990
1991 return &instruction->base;
1992}
1993
1994static Stage1ZirInst *ir_build_int_to_float(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
1995 Stage1ZirInst *dest_type, Stage1ZirInst *target)
1996{
1997 Stage1ZirInstIntToFloat *instruction = ir_build_instruction<Stage1ZirInstIntToFloat>(ag, scope, source_node);
1998 instruction->dest_type = dest_type;
1999 instruction->target = target;
2000
2001 ir_ref_instruction(dest_type, ag->current_basic_block);
2002 ir_ref_instruction(target, ag->current_basic_block);
2003
2004 return &instruction->base;
2005}
2006
2007static Stage1ZirInst *ir_build_float_to_int(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2008 Stage1ZirInst *dest_type, Stage1ZirInst *target)
2009{
2010 Stage1ZirInstFloatToInt *instruction = ir_build_instruction<Stage1ZirInstFloatToInt>(ag, scope, source_node);
2011 instruction->dest_type = dest_type;
2012 instruction->target = target;
2013
2014 ir_ref_instruction(dest_type, ag->current_basic_block);
2015 ir_ref_instruction(target, ag->current_basic_block);
2016
2017 return &instruction->base;
2018}
2019
2020static Stage1ZirInst *ir_build_bool_to_int(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *target) {
2021 Stage1ZirInstBoolToInt *instruction = ir_build_instruction<Stage1ZirInstBoolToInt>(ag, scope, source_node);
2022 instruction->target = target;
2023
2024 ir_ref_instruction(target, ag->current_basic_block);
2025
2026 return &instruction->base;
2027}
2028
2029static Stage1ZirInst *ir_build_vector_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *len,
2030 Stage1ZirInst *elem_type)
2031{
2032 Stage1ZirInstVectorType *instruction = ir_build_instruction<Stage1ZirInstVectorType>(ag, scope, source_node);
2033 instruction->len = len;
2034 instruction->elem_type = elem_type;
2035
2036 ir_ref_instruction(len, ag->current_basic_block);
2037 ir_ref_instruction(elem_type, ag->current_basic_block);
2038
2039 return &instruction->base;
2040}
2041
2042static Stage1ZirInst *ir_build_shuffle_vector(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2043 Stage1ZirInst *scalar_type, Stage1ZirInst *a, Stage1ZirInst *b, Stage1ZirInst *mask)
2044{
2045 Stage1ZirInstShuffleVector *instruction = ir_build_instruction<Stage1ZirInstShuffleVector>(ag, scope, source_node);
2046 instruction->scalar_type = scalar_type;
2047 instruction->a = a;
2048 instruction->b = b;
2049 instruction->mask = mask;
2050
2051 if (scalar_type != nullptr) ir_ref_instruction(scalar_type, ag->current_basic_block);
2052 ir_ref_instruction(a, ag->current_basic_block);
2053 ir_ref_instruction(b, ag->current_basic_block);
2054 ir_ref_instruction(mask, ag->current_basic_block);
2055
2056 return &instruction->base;
2057}
2058
2059static Stage1ZirInst *ir_build_select(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2060 Stage1ZirInst *scalar_type, Stage1ZirInst *pred, Stage1ZirInst *a, Stage1ZirInst *b)
2061{
2062 Stage1ZirInstSelect *instruction = ir_build_instruction<Stage1ZirInstSelect>(ag, scope, source_node);
2063 instruction->scalar_type = scalar_type;
2064 instruction->pred = pred;
2065 instruction->a = a;
2066 instruction->b = b;
2067
2068 ir_ref_instruction(pred, ag->current_basic_block);
2069 ir_ref_instruction(a, ag->current_basic_block);
2070 ir_ref_instruction(b, ag->current_basic_block);
2071
2072 return &instruction->base;
2073}
2074
2075static Stage1ZirInst *ir_build_splat_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2076 Stage1ZirInst *len, Stage1ZirInst *scalar)
2077{
2078 Stage1ZirInstSplat *instruction = ir_build_instruction<Stage1ZirInstSplat>(ag, scope, source_node);
2079 instruction->len = len;
2080 instruction->scalar = scalar;
2081
2082 ir_ref_instruction(len, ag->current_basic_block);
2083 ir_ref_instruction(scalar, ag->current_basic_block);
2084
2085 return &instruction->base;
2086}
2087
2088static Stage1ZirInst *ir_build_bool_not(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *value) {
2089 Stage1ZirInstBoolNot *instruction = ir_build_instruction<Stage1ZirInstBoolNot>(ag, scope, source_node);
2090 instruction->value = value;
2091
2092 ir_ref_instruction(value, ag->current_basic_block);
2093
2094 return &instruction->base;
2095}
2096
2097static Stage1ZirInst *ir_build_memset_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2098 Stage1ZirInst *dest_ptr, Stage1ZirInst *byte, Stage1ZirInst *count)
2099{
2100 Stage1ZirInstMemset *instruction = ir_build_instruction<Stage1ZirInstMemset>(ag, scope, source_node);
2101 instruction->dest_ptr = dest_ptr;
2102 instruction->byte = byte;
2103 instruction->count = count;
2104
2105 ir_ref_instruction(dest_ptr, ag->current_basic_block);
2106 ir_ref_instruction(byte, ag->current_basic_block);
2107 ir_ref_instruction(count, ag->current_basic_block);
2108
2109 return &instruction->base;
2110}
2111
2112static Stage1ZirInst *ir_build_memcpy_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2113 Stage1ZirInst *dest_ptr, Stage1ZirInst *src_ptr, Stage1ZirInst *count)
2114{
2115 Stage1ZirInstMemcpy *instruction = ir_build_instruction<Stage1ZirInstMemcpy>(ag, scope, source_node);
2116 instruction->dest_ptr = dest_ptr;
2117 instruction->src_ptr = src_ptr;
2118 instruction->count = count;
2119
2120 ir_ref_instruction(dest_ptr, ag->current_basic_block);
2121 ir_ref_instruction(src_ptr, ag->current_basic_block);
2122 ir_ref_instruction(count, ag->current_basic_block);
2123
2124 return &instruction->base;
2125}
2126
2127static Stage1ZirInst *ir_build_slice_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2128 Stage1ZirInst *ptr, Stage1ZirInst *start, Stage1ZirInst *end, Stage1ZirInst *sentinel,
2129 bool safety_check_on, ResultLoc *result_loc)
2130{
2131 Stage1ZirInstSlice *instruction = ir_build_instruction<Stage1ZirInstSlice>(ag, scope, source_node);
2132 instruction->ptr = ptr;
2133 instruction->start = start;
2134 instruction->end = end;
2135 instruction->sentinel = sentinel;
2136 instruction->safety_check_on = safety_check_on;
2137 instruction->result_loc = result_loc;
2138
2139 ir_ref_instruction(ptr, ag->current_basic_block);
2140 ir_ref_instruction(start, ag->current_basic_block);
2141 if (end) ir_ref_instruction(end, ag->current_basic_block);
2142 if (sentinel) ir_ref_instruction(sentinel, ag->current_basic_block);
2143
2144 return &instruction->base;
2145}
2146
2147static Stage1ZirInst *ir_build_breakpoint(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
2148 Stage1ZirInstBreakpoint *instruction = ir_build_instruction<Stage1ZirInstBreakpoint>(ag, scope, source_node);
2149 return &instruction->base;
2150}
2151
2152static Stage1ZirInst *ir_build_return_address_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
2153 Stage1ZirInstReturnAddress *instruction = ir_build_instruction<Stage1ZirInstReturnAddress>(ag, scope, source_node);
2154 return &instruction->base;
2155}
2156
2157static Stage1ZirInst *ir_build_frame_address_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
2158 Stage1ZirInstFrameAddress *inst = ir_build_instruction<Stage1ZirInstFrameAddress>(ag, scope, source_node);
2159 return &inst->base;
2160}
2161
2162static Stage1ZirInst *ir_build_handle_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
2163 Stage1ZirInstFrameHandle *inst = ir_build_instruction<Stage1ZirInstFrameHandle>(ag, scope, source_node);
2164 return &inst->base;
2165}
2166
2167static Stage1ZirInst *ir_build_frame_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *fn) {
2168 Stage1ZirInstFrameType *inst = ir_build_instruction<Stage1ZirInstFrameType>(ag, scope, source_node);
2169 inst->fn = fn;
2170
2171 ir_ref_instruction(fn, ag->current_basic_block);
2172
2173 return &inst->base;
2174}
2175
2176static Stage1ZirInst *ir_build_frame_size_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *fn) {
2177 Stage1ZirInstFrameSize *inst = ir_build_instruction<Stage1ZirInstFrameSize>(ag, scope, source_node);
2178 inst->fn = fn;
2179
2180 ir_ref_instruction(fn, ag->current_basic_block);
2181
2182 return &inst->base;
2183}
2184
2185static Stage1ZirInst *ir_build_overflow_op_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2186 IrOverflowOp op, Stage1ZirInst *type_value, Stage1ZirInst *op1, Stage1ZirInst *op2, Stage1ZirInst *result_ptr)
2187{
2188 Stage1ZirInstOverflowOp *instruction = ir_build_instruction<Stage1ZirInstOverflowOp>(ag, scope, source_node);
2189 instruction->op = op;
2190 instruction->type_value = type_value;
2191 instruction->op1 = op1;
2192 instruction->op2 = op2;
2193 instruction->result_ptr = result_ptr;
2194
2195 ir_ref_instruction(type_value, ag->current_basic_block);
2196 ir_ref_instruction(op1, ag->current_basic_block);
2197 ir_ref_instruction(op2, ag->current_basic_block);
2198 ir_ref_instruction(result_ptr, ag->current_basic_block);
2199
2200 return &instruction->base;
2201}
2202
2203static Stage1ZirInst *ir_build_float_op_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *operand,
2204 BuiltinFnId fn_id)
2205{
2206 Stage1ZirInstFloatOp *instruction = ir_build_instruction<Stage1ZirInstFloatOp>(ag, scope, source_node);
2207 instruction->operand = operand;
2208 instruction->fn_id = fn_id;
2209
2210 ir_ref_instruction(operand, ag->current_basic_block);
2211
2212 return &instruction->base;
2213}
2214
2215static Stage1ZirInst *ir_build_mul_add_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2216 Stage1ZirInst *type_value, Stage1ZirInst *op1, Stage1ZirInst *op2, Stage1ZirInst *op3)
2217{
2218 Stage1ZirInstMulAdd *instruction = ir_build_instruction<Stage1ZirInstMulAdd>(ag, scope, source_node);
2219 instruction->type_value = type_value;
2220 instruction->op1 = op1;
2221 instruction->op2 = op2;
2222 instruction->op3 = op3;
2223
2224 ir_ref_instruction(type_value, ag->current_basic_block);
2225 ir_ref_instruction(op1, ag->current_basic_block);
2226 ir_ref_instruction(op2, ag->current_basic_block);
2227 ir_ref_instruction(op3, ag->current_basic_block);
2228
2229 return &instruction->base;
2230}
2231
2232static Stage1ZirInst *ir_build_align_of(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *type_value) {
2233 Stage1ZirInstAlignOf *instruction = ir_build_instruction<Stage1ZirInstAlignOf>(ag, scope, source_node);
2234 instruction->type_value = type_value;
2235
2236 ir_ref_instruction(type_value, ag->current_basic_block);
2237
2238 return &instruction->base;
2239}
2240
2241static Stage1ZirInst *ir_build_test_err_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2242 Stage1ZirInst *base_ptr, bool resolve_err_set, bool base_ptr_is_payload)
2243{
2244 Stage1ZirInstTestErr *instruction = ir_build_instruction<Stage1ZirInstTestErr>(ag, scope, source_node);
2245 instruction->base_ptr = base_ptr;
2246 instruction->resolve_err_set = resolve_err_set;
2247 instruction->base_ptr_is_payload = base_ptr_is_payload;
2248
2249 ir_ref_instruction(base_ptr, ag->current_basic_block);
2250
2251 return &instruction->base;
2252}
2253
2254static Stage1ZirInst *ir_build_unwrap_err_code_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2255 Stage1ZirInst *err_union_ptr)
2256{
2257 Stage1ZirInstUnwrapErrCode *inst = ir_build_instruction<Stage1ZirInstUnwrapErrCode>(ag, scope, source_node);
2258 inst->err_union_ptr = err_union_ptr;
2259
2260 ir_ref_instruction(err_union_ptr, ag->current_basic_block);
2261
2262 return &inst->base;
2263}
2264
2265static Stage1ZirInst *ir_build_unwrap_err_payload_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2266 Stage1ZirInst *value, bool safety_check_on, bool initializing)
2267{
2268 Stage1ZirInstUnwrapErrPayload *inst = ir_build_instruction<Stage1ZirInstUnwrapErrPayload>(ag, scope, source_node);
2269 inst->value = value;
2270 inst->safety_check_on = safety_check_on;
2271 inst->initializing = initializing;
2272
2273 ir_ref_instruction(value, ag->current_basic_block);
2274
2275 return &inst->base;
2276}
2277
2278static Stage1ZirInst *ir_build_fn_proto(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2279 Stage1ZirInst **param_types, Stage1ZirInst *align_value, Stage1ZirInst *callconv_value,
2280 Stage1ZirInst *return_type, bool is_var_args)
2281{
2282 Stage1ZirInstFnProto *instruction = ir_build_instruction<Stage1ZirInstFnProto>(ag, scope, source_node);
2283 instruction->param_types = param_types;
2284 instruction->align_value = align_value;
2285 instruction->callconv_value = callconv_value;
2286 instruction->return_type = return_type;
2287 instruction->is_var_args = is_var_args;
2288
2289 assert(source_node->type == NodeTypeFnProto);
2290 size_t param_count = source_node->data.fn_proto.params.length;
2291 if (is_var_args) param_count -= 1;
2292 for (size_t i = 0; i < param_count; i += 1) {
2293 if (param_types[i] != nullptr) ir_ref_instruction(param_types[i], ag->current_basic_block);
2294 }
2295 if (align_value != nullptr) ir_ref_instruction(align_value, ag->current_basic_block);
2296 if (callconv_value != nullptr) ir_ref_instruction(callconv_value, ag->current_basic_block);
2297 ir_ref_instruction(return_type, ag->current_basic_block);
2298
2299 return &instruction->base;
2300}
2301
2302static Stage1ZirInst *ir_build_test_comptime(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *value) {
2303 Stage1ZirInstTestComptime *instruction = ir_build_instruction<Stage1ZirInstTestComptime>(ag, scope, source_node);
2304 instruction->value = value;
2305
2306 ir_ref_instruction(value, ag->current_basic_block);
2307
2308 return &instruction->base;
2309}
2310
2311static Stage1ZirInst *ir_build_ptr_cast_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2312 Stage1ZirInst *dest_type, Stage1ZirInst *ptr, bool safety_check_on)
2313{
2314 Stage1ZirInstPtrCast *instruction = ir_build_instruction<Stage1ZirInstPtrCast>(
2315 ag, scope, source_node);
2316 instruction->dest_type = dest_type;
2317 instruction->ptr = ptr;
2318 instruction->safety_check_on = safety_check_on;
2319
2320 ir_ref_instruction(dest_type, ag->current_basic_block);
2321 ir_ref_instruction(ptr, ag->current_basic_block);
2322
2323 return &instruction->base;
2324}
2325
2326static Stage1ZirInst *ir_build_implicit_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2327 Stage1ZirInst *operand, ResultLocCast *result_loc_cast)
2328{
2329 Stage1ZirInstImplicitCast *instruction = ir_build_instruction<Stage1ZirInstImplicitCast>(ag, scope, source_node);
2330 instruction->operand = operand;
2331 instruction->result_loc_cast = result_loc_cast;
2332
2333 ir_ref_instruction(operand, ag->current_basic_block);
2334
2335 return &instruction->base;
2336}
2337
2338static Stage1ZirInst *ir_build_bit_cast_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2339 Stage1ZirInst *operand, ResultLocBitCast *result_loc_bit_cast)
2340{
2341 Stage1ZirInstBitCast *instruction = ir_build_instruction<Stage1ZirInstBitCast>(ag, scope, source_node);
2342 instruction->operand = operand;
2343 instruction->result_loc_bit_cast = result_loc_bit_cast;
2344
2345 ir_ref_instruction(operand, ag->current_basic_block);
2346
2347 return &instruction->base;
2348}
2349
2350static Stage1ZirInst *ir_build_int_to_ptr_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2351 Stage1ZirInst *dest_type, Stage1ZirInst *target)
2352{
2353 Stage1ZirInstIntToPtr *instruction = ir_build_instruction<Stage1ZirInstIntToPtr>(ag, scope, source_node);
2354 instruction->dest_type = dest_type;
2355 instruction->target = target;
2356
2357 ir_ref_instruction(dest_type, ag->current_basic_block);
2358 ir_ref_instruction(target, ag->current_basic_block);
2359
2360 return &instruction->base;
2361}
2362
2363static Stage1ZirInst *ir_build_ptr_to_int_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2364 Stage1ZirInst *target)
2365{
2366 Stage1ZirInstPtrToInt *inst = ir_build_instruction<Stage1ZirInstPtrToInt>(ag, scope, source_node);
2367 inst->target = target;
2368
2369 ir_ref_instruction(target, ag->current_basic_block);
2370
2371 return &inst->base;
2372}
2373
2374static Stage1ZirInst *ir_build_int_to_enum_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2375 Stage1ZirInst *dest_type, Stage1ZirInst *target)
2376{
2377 Stage1ZirInstIntToEnum *instruction = ir_build_instruction<Stage1ZirInstIntToEnum>(ag, scope, source_node);
2378 instruction->dest_type = dest_type;
2379 instruction->target = target;
2380
2381 if (dest_type) ir_ref_instruction(dest_type, ag->current_basic_block);
2382 ir_ref_instruction(target, ag->current_basic_block);
2383
2384 return &instruction->base;
2385}
2386
2387static Stage1ZirInst *ir_build_enum_to_int(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2388 Stage1ZirInst *target)
2389{
2390 Stage1ZirInstEnumToInt *instruction = ir_build_instruction<Stage1ZirInstEnumToInt>(
2391 ag, scope, source_node);
2392 instruction->target = target;
2393
2394 ir_ref_instruction(target, ag->current_basic_block);
2395
2396 return &instruction->base;
2397}
2398
2399static Stage1ZirInst *ir_build_int_to_err_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2400 Stage1ZirInst *target)
2401{
2402 Stage1ZirInstIntToErr *instruction = ir_build_instruction<Stage1ZirInstIntToErr>(ag, scope, source_node);
2403 instruction->target = target;
2404
2405 ir_ref_instruction(target, ag->current_basic_block);
2406
2407 return &instruction->base;
2408}
2409
2410static Stage1ZirInst *ir_build_err_to_int_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2411 Stage1ZirInst *target)
2412{
2413 Stage1ZirInstErrToInt *instruction = ir_build_instruction<Stage1ZirInstErrToInt>(
2414 ag, scope, source_node);
2415 instruction->target = target;
2416
2417 ir_ref_instruction(target, ag->current_basic_block);
2418
2419 return &instruction->base;
2420}
2421
2422static Stage1ZirInst *ir_build_check_switch_prongs(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2423 Stage1ZirInst *target_value, Stage1ZirInstCheckSwitchProngsRange *ranges, size_t range_count,
2424 AstNode* else_prong, bool have_underscore_prong)
2425{
2426 Stage1ZirInstCheckSwitchProngs *instruction = heap::c_allocator.create<Stage1ZirInstCheckSwitchProngs>();
2427 instruction->base.id = have_underscore_prong ?
2428 Stage1ZirInstIdCheckSwitchProngsUnderYes : Stage1ZirInstIdCheckSwitchProngsUnderNo;
2429 instruction->base.scope = scope;
2430 instruction->base.source_node = source_node;
2431 instruction->base.debug_id = irb_next_debug_id(ag);
2432 instruction->base.owner_bb = ag->current_basic_block;
2433 ir_instruction_append(ag->current_basic_block, &instruction->base);
2434
2435 instruction->target_value = target_value;
2436 instruction->ranges = ranges;
2437 instruction->range_count = range_count;
2438 instruction->else_prong = else_prong;
2439
2440 ir_ref_instruction(target_value, ag->current_basic_block);
2441 for (size_t i = 0; i < range_count; i += 1) {
2442 ir_ref_instruction(ranges[i].start, ag->current_basic_block);
2443 ir_ref_instruction(ranges[i].end, ag->current_basic_block);
2444 }
2445
2446 return &instruction->base;
2447}
2448
2449static Stage1ZirInst *ir_build_check_statement_is_void(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2450 Stage1ZirInst* statement_value)
2451{
2452 Stage1ZirInstCheckStatementIsVoid *instruction = ir_build_instruction<Stage1ZirInstCheckStatementIsVoid>(
2453 ag, scope, source_node);
2454 instruction->statement_value = statement_value;
2455
2456 ir_ref_instruction(statement_value, ag->current_basic_block);
2457
2458 return &instruction->base;
2459}
2460
2461static Stage1ZirInst *ir_build_type_name(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2462 Stage1ZirInst *type_value)
2463{
2464 Stage1ZirInstTypeName *instruction = ir_build_instruction<Stage1ZirInstTypeName>(ag, scope, source_node);
2465 instruction->type_value = type_value;
2466
2467 ir_ref_instruction(type_value, ag->current_basic_block);
2468
2469 return &instruction->base;
2470}
2471
2472static Stage1ZirInst *ir_build_decl_ref(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Tld *tld, LVal lval) {
2473 Stage1ZirInstDeclRef *instruction = ir_build_instruction<Stage1ZirInstDeclRef>(ag, scope, source_node);
2474 instruction->tld = tld;
2475 instruction->lval = lval;
2476
2477 return &instruction->base;
2478}
2479
2480static Stage1ZirInst *ir_build_panic_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *msg) {
2481 Stage1ZirInstPanic *instruction = ir_build_instruction<Stage1ZirInstPanic>(ag, scope, source_node);
2482 instruction->msg = msg;
2483
2484 ir_ref_instruction(msg, ag->current_basic_block);
2485
2486 return &instruction->base;
2487}
2488
2489static Stage1ZirInst *ir_build_tag_name_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *target) {
2490 Stage1ZirInstTagName *instruction = ir_build_instruction<Stage1ZirInstTagName>(ag, scope, source_node);
2491 instruction->target = target;
2492
2493 ir_ref_instruction(target, ag->current_basic_block);
2494
2495 return &instruction->base;
2496}
2497
2498static Stage1ZirInst *ir_build_field_parent_ptr_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2499 Stage1ZirInst *type_value, Stage1ZirInst *field_name, Stage1ZirInst *field_ptr)
2500{
2501 Stage1ZirInstFieldParentPtr *inst = ir_build_instruction<Stage1ZirInstFieldParentPtr>(
2502 ag, scope, source_node);
2503 inst->type_value = type_value;
2504 inst->field_name = field_name;
2505 inst->field_ptr = field_ptr;
2506
2507 ir_ref_instruction(type_value, ag->current_basic_block);
2508 ir_ref_instruction(field_name, ag->current_basic_block);
2509 ir_ref_instruction(field_ptr, ag->current_basic_block);
2510
2511 return &inst->base;
2512}
2513
2514static Stage1ZirInst *ir_build_offset_of(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2515 Stage1ZirInst *type_value, Stage1ZirInst *field_name)
2516{
2517 Stage1ZirInstOffsetOf *instruction = ir_build_instruction<Stage1ZirInstOffsetOf>(ag, scope, source_node);
2518 instruction->type_value = type_value;
2519 instruction->field_name = field_name;
2520
2521 ir_ref_instruction(type_value, ag->current_basic_block);
2522 ir_ref_instruction(field_name, ag->current_basic_block);
2523
2524 return &instruction->base;
2525}
2526
2527static Stage1ZirInst *ir_build_bit_offset_of(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2528 Stage1ZirInst *type_value, Stage1ZirInst *field_name)
2529{
2530 Stage1ZirInstBitOffsetOf *instruction = ir_build_instruction<Stage1ZirInstBitOffsetOf>(ag, scope, source_node);
2531 instruction->type_value = type_value;
2532 instruction->field_name = field_name;
2533
2534 ir_ref_instruction(type_value, ag->current_basic_block);
2535 ir_ref_instruction(field_name, ag->current_basic_block);
2536
2537 return &instruction->base;
2538}
2539
2540static Stage1ZirInst *ir_build_type_info(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *type_value) {
2541 Stage1ZirInstTypeInfo *instruction = ir_build_instruction<Stage1ZirInstTypeInfo>(ag, scope, source_node);
2542 instruction->type_value = type_value;
2543
2544 ir_ref_instruction(type_value, ag->current_basic_block);
2545
2546 return &instruction->base;
2547}
2548
2549static Stage1ZirInst *ir_build_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *type_info) {
2550 Stage1ZirInstType *instruction = ir_build_instruction<Stage1ZirInstType>(ag, scope, source_node);
2551 instruction->type_info = type_info;
2552
2553 ir_ref_instruction(type_info, ag->current_basic_block);
2554
2555 return &instruction->base;
2556}
2557
2558static Stage1ZirInst *ir_build_set_eval_branch_quota(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2559 Stage1ZirInst *new_quota)
2560{
2561 Stage1ZirInstSetEvalBranchQuota *instruction = ir_build_instruction<Stage1ZirInstSetEvalBranchQuota>(ag, scope, source_node);
2562 instruction->new_quota = new_quota;
2563
2564 ir_ref_instruction(new_quota, ag->current_basic_block);
2565
2566 return &instruction->base;
2567}
2568
2569static Stage1ZirInst *ir_build_align_cast_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2570 Stage1ZirInst *align_bytes, Stage1ZirInst *target)
2571{
2572 Stage1ZirInstAlignCast *instruction = ir_build_instruction<Stage1ZirInstAlignCast>(ag, scope, source_node);
2573 instruction->align_bytes = align_bytes;
2574 instruction->target = target;
2575
2576 ir_ref_instruction(align_bytes, ag->current_basic_block);
2577 ir_ref_instruction(target, ag->current_basic_block);
2578
2579 return &instruction->base;
2580}
2581
2582static Stage1ZirInst *ir_build_addrspace_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2583 Stage1ZirInst *addrspace, Stage1ZirInst *ptr)
2584{
2585 Stage1ZirInstAddrSpaceCast *instruction = ir_build_instruction<Stage1ZirInstAddrSpaceCast>(ag, scope, source_node);
2586 instruction->addrspace = addrspace;
2587 instruction->ptr = ptr;
2588
2589 ir_ref_instruction(addrspace, ag->current_basic_block);
2590 ir_ref_instruction(ptr, ag->current_basic_block);
2591
2592 return &instruction->base;
2593}
2594
2595static Stage1ZirInst *ir_build_resolve_result(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2596 ResultLoc *result_loc, Stage1ZirInst *ty)
2597{
2598 Stage1ZirInstResolveResult *instruction = ir_build_instruction<Stage1ZirInstResolveResult>(ag, scope, source_node);
2599 instruction->result_loc = result_loc;
2600 instruction->ty = ty;
2601
2602 if (ty != nullptr) ir_ref_instruction(ty, ag->current_basic_block);
2603
2604 return &instruction->base;
2605}
2606
2607static Stage1ZirInst *ir_build_reset_result(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2608 ResultLoc *result_loc)
2609{
2610 Stage1ZirInstResetResult *instruction = ir_build_instruction<Stage1ZirInstResetResult>(ag, scope, source_node);
2611 instruction->result_loc = result_loc;
2612
2613 return &instruction->base;
2614}
2615
2616static Stage1ZirInst *ir_build_set_align_stack(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2617 Stage1ZirInst *align_bytes)
2618{
2619 Stage1ZirInstSetAlignStack *instruction = ir_build_instruction<Stage1ZirInstSetAlignStack>(ag, scope, source_node);
2620 instruction->align_bytes = align_bytes;
2621
2622 ir_ref_instruction(align_bytes, ag->current_basic_block);
2623
2624 return &instruction->base;
2625}
2626
2627static Stage1ZirInst *ir_build_arg_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2628 Stage1ZirInst *fn_type, Stage1ZirInst *arg_index, bool allow_var)
2629{
2630 Stage1ZirInstArgType *instruction = heap::c_allocator.create<Stage1ZirInstArgType>();
2631 instruction->base.id = allow_var ?
2632 Stage1ZirInstIdArgTypeAllowVarTrue : Stage1ZirInstIdArgTypeAllowVarFalse;
2633 instruction->base.scope = scope;
2634 instruction->base.source_node = source_node;
2635 instruction->base.debug_id = irb_next_debug_id(ag);
2636 instruction->base.owner_bb = ag->current_basic_block;
2637 ir_instruction_append(ag->current_basic_block, &instruction->base);
2638
2639 instruction->fn_type = fn_type;
2640 instruction->arg_index = arg_index;
2641
2642 ir_ref_instruction(fn_type, ag->current_basic_block);
2643 ir_ref_instruction(arg_index, ag->current_basic_block);
2644
2645 return &instruction->base;
2646}
2647
2648static Stage1ZirInst *ir_build_error_return_trace_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2649 IrInstErrorReturnTraceOptional optional)
2650{
2651 Stage1ZirInstErrorReturnTrace *inst = ir_build_instruction<Stage1ZirInstErrorReturnTrace>(ag, scope, source_node);
2652 inst->optional = optional;
2653
2654 return &inst->base;
2655}
2656
2657static Stage1ZirInst *ir_build_error_union(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2658 Stage1ZirInst *err_set, Stage1ZirInst *payload)
2659{
2660 Stage1ZirInstErrorUnion *instruction = ir_build_instruction<Stage1ZirInstErrorUnion>(ag, scope, source_node);
2661 instruction->err_set = err_set;
2662 instruction->payload = payload;
2663
2664 ir_ref_instruction(err_set, ag->current_basic_block);
2665 ir_ref_instruction(payload, ag->current_basic_block);
2666
2667 return &instruction->base;
2668}
2669
2670static Stage1ZirInst *ir_build_atomic_rmw_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2671 Stage1ZirInst *operand_type, Stage1ZirInst *ptr, Stage1ZirInst *op, Stage1ZirInst *operand,
2672 Stage1ZirInst *ordering)
2673{
2674 Stage1ZirInstAtomicRmw *instruction = ir_build_instruction<Stage1ZirInstAtomicRmw>(ag, scope, source_node);
2675 instruction->operand_type = operand_type;
2676 instruction->ptr = ptr;
2677 instruction->op = op;
2678 instruction->operand = operand;
2679 instruction->ordering = ordering;
2680
2681 ir_ref_instruction(operand_type, ag->current_basic_block);
2682 ir_ref_instruction(ptr, ag->current_basic_block);
2683 ir_ref_instruction(op, ag->current_basic_block);
2684 ir_ref_instruction(operand, ag->current_basic_block);
2685 ir_ref_instruction(ordering, ag->current_basic_block);
2686
2687 return &instruction->base;
2688}
2689
2690static Stage1ZirInst *ir_build_atomic_load_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2691 Stage1ZirInst *operand_type, Stage1ZirInst *ptr, Stage1ZirInst *ordering)
2692{
2693 Stage1ZirInstAtomicLoad *instruction = ir_build_instruction<Stage1ZirInstAtomicLoad>(ag, scope, source_node);
2694 instruction->operand_type = operand_type;
2695 instruction->ptr = ptr;
2696 instruction->ordering = ordering;
2697
2698 ir_ref_instruction(operand_type, ag->current_basic_block);
2699 ir_ref_instruction(ptr, ag->current_basic_block);
2700 ir_ref_instruction(ordering, ag->current_basic_block);
2701
2702 return &instruction->base;
2703}
2704
2705static Stage1ZirInst *ir_build_atomic_store_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2706 Stage1ZirInst *operand_type, Stage1ZirInst *ptr, Stage1ZirInst *value, Stage1ZirInst *ordering)
2707{
2708 Stage1ZirInstAtomicStore *instruction = ir_build_instruction<Stage1ZirInstAtomicStore>(ag, scope, source_node);
2709 instruction->operand_type = operand_type;
2710 instruction->ptr = ptr;
2711 instruction->value = value;
2712 instruction->ordering = ordering;
2713
2714 ir_ref_instruction(operand_type, ag->current_basic_block);
2715 ir_ref_instruction(ptr, ag->current_basic_block);
2716 ir_ref_instruction(value, ag->current_basic_block);
2717 ir_ref_instruction(ordering, ag->current_basic_block);
2718
2719 return &instruction->base;
2720}
2721
2722static Stage1ZirInst *ir_build_save_err_ret_addr_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
2723 Stage1ZirInstSaveErrRetAddr *inst = ir_build_instruction<Stage1ZirInstSaveErrRetAddr>(ag, scope, source_node);
2724 return &inst->base;
2725}
2726
2727static Stage1ZirInst *ir_build_add_implicit_return_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2728 Stage1ZirInst *value, ResultLocReturn *result_loc_ret)
2729{
2730 Stage1ZirInstAddImplicitReturnType *inst = ir_build_instruction<Stage1ZirInstAddImplicitReturnType>(ag, scope, source_node);
2731 inst->value = value;
2732 inst->result_loc_ret = result_loc_ret;
2733
2734 ir_ref_instruction(value, ag->current_basic_block);
2735
2736 return &inst->base;
2737}
2738
2739static Stage1ZirInst *ir_build_has_decl(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2740 Stage1ZirInst *container, Stage1ZirInst *name)
2741{
2742 Stage1ZirInstHasDecl *instruction = ir_build_instruction<Stage1ZirInstHasDecl>(ag, scope, source_node);
2743 instruction->container = container;
2744 instruction->name = name;
2745
2746 ir_ref_instruction(container, ag->current_basic_block);
2747 ir_ref_instruction(name, ag->current_basic_block);
2748
2749 return &instruction->base;
2750}
2751
2752static Stage1ZirInst *ir_build_undeclared_identifier(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Buf *name) {
2753 Stage1ZirInstUndeclaredIdent *instruction = ir_build_instruction<Stage1ZirInstUndeclaredIdent>(ag, scope, source_node);
2754 instruction->name = name;
2755
2756 return &instruction->base;
2757}
2758
2759static Stage1ZirInst *ir_build_check_runtime_scope(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *scope_is_comptime, Stage1ZirInst *is_comptime) {
2760 Stage1ZirInstCheckRuntimeScope *instruction = ir_build_instruction<Stage1ZirInstCheckRuntimeScope>(ag, scope, source_node);
2761 instruction->scope_is_comptime = scope_is_comptime;
2762 instruction->is_comptime = is_comptime;
2763
2764 ir_ref_instruction(scope_is_comptime, ag->current_basic_block);
2765 ir_ref_instruction(is_comptime, ag->current_basic_block);
2766
2767 return &instruction->base;
2768}
2769
2770static Stage1ZirInst *ir_build_union_init_named_field(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2771 Stage1ZirInst *union_type, Stage1ZirInst *field_name, Stage1ZirInst *field_result_loc, Stage1ZirInst *result_loc)
2772{
2773 Stage1ZirInstUnionInitNamedField *instruction = ir_build_instruction<Stage1ZirInstUnionInitNamedField>(ag, scope, source_node);
2774 instruction->union_type = union_type;
2775 instruction->field_name = field_name;
2776 instruction->field_result_loc = field_result_loc;
2777 instruction->result_loc = result_loc;
2778
2779 ir_ref_instruction(union_type, ag->current_basic_block);
2780 ir_ref_instruction(field_name, ag->current_basic_block);
2781 ir_ref_instruction(field_result_loc, ag->current_basic_block);
2782 if (result_loc != nullptr) ir_ref_instruction(result_loc, ag->current_basic_block);
2783
2784 return &instruction->base;
2785}
2786
2787static Stage1ZirInst *ir_build_alloca_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2788 Stage1ZirInst *align, const char *name_hint, Stage1ZirInst *is_comptime)
2789{
2790 Stage1ZirInstAlloca *instruction = ir_build_instruction<Stage1ZirInstAlloca>(ag, scope, source_node);
2791 instruction->align = align;
2792 instruction->name_hint = name_hint;
2793 instruction->is_comptime = is_comptime;
2794
2795 if (align != nullptr) ir_ref_instruction(align, ag->current_basic_block);
2796 if (is_comptime != nullptr) ir_ref_instruction(is_comptime, ag->current_basic_block);
2797
2798 return &instruction->base;
2799}
2800
2801static Stage1ZirInst *ir_build_end_expr(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2802 Stage1ZirInst *value, ResultLoc *result_loc)
2803{
2804 Stage1ZirInstEndExpr *instruction = ir_build_instruction<Stage1ZirInstEndExpr>(ag, scope, source_node);
2805 instruction->value = value;
2806 instruction->result_loc = result_loc;
2807
2808 ir_ref_instruction(value, ag->current_basic_block);
2809
2810 return &instruction->base;
2811}
2812
2813static Stage1ZirInstSuspendBegin *ir_build_suspend_begin_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
2814 return ir_build_instruction<Stage1ZirInstSuspendBegin>(ag, scope, source_node);
2815}
2816
2817static Stage1ZirInst *ir_build_suspend_finish_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2818 Stage1ZirInstSuspendBegin *begin)
2819{
2820 Stage1ZirInstSuspendFinish *inst = ir_build_instruction<Stage1ZirInstSuspendFinish>(ag, scope, source_node);
2821 inst->begin = begin;
2822
2823 ir_ref_instruction(&begin->base, ag->current_basic_block);
2824
2825 return &inst->base;
2826}
2827
2828static Stage1ZirInst *ir_build_await_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2829 Stage1ZirInst *frame, ResultLoc *result_loc, bool is_nosuspend)
2830{
2831 Stage1ZirInstAwait *instruction = ir_build_instruction<Stage1ZirInstAwait>(ag, scope, source_node);
2832 instruction->frame = frame;
2833 instruction->result_loc = result_loc;
2834 instruction->is_nosuspend = is_nosuspend;
2835
2836 ir_ref_instruction(frame, ag->current_basic_block);
2837
2838 return &instruction->base;
2839}
2840
2841static Stage1ZirInst *ir_build_resume_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *frame) {
2842 Stage1ZirInstResume *instruction = ir_build_instruction<Stage1ZirInstResume>(ag, scope, source_node);
2843 instruction->frame = frame;
2844
2845 ir_ref_instruction(frame, ag->current_basic_block);
2846
2847 return &instruction->base;
2848}
2849
2850static Stage1ZirInstSpillBegin *ir_build_spill_begin_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2851 Stage1ZirInst *operand, SpillId spill_id)
2852{
2853 Stage1ZirInstSpillBegin *instruction = ir_build_instruction<Stage1ZirInstSpillBegin>(ag, scope, source_node);
2854 instruction->operand = operand;
2855 instruction->spill_id = spill_id;
2856
2857 ir_ref_instruction(operand, ag->current_basic_block);
2858
2859 return instruction;
2860}
2861
2862static Stage1ZirInst *ir_build_spill_end_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2863 Stage1ZirInstSpillBegin *begin)
2864{
2865 Stage1ZirInstSpillEnd *instruction = ir_build_instruction<Stage1ZirInstSpillEnd>(ag, scope, source_node);
2866 instruction->begin = begin;
2867
2868 ir_ref_instruction(&begin->base, ag->current_basic_block);
2869
2870 return &instruction->base;
2871}
2872
2873static Stage1ZirInst *ir_build_wasm_memory_size_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *index) {
2874 Stage1ZirInstWasmMemorySize *instruction = ir_build_instruction<Stage1ZirInstWasmMemorySize>(ag, scope, source_node);
2875 instruction->index = index;
2876
2877 ir_ref_instruction(index, ag->current_basic_block);
2878
2879 return &instruction->base;
2880}
2881
2882static Stage1ZirInst *ir_build_wasm_memory_grow_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Stage1ZirInst *index, Stage1ZirInst *delta) {
2883 Stage1ZirInstWasmMemoryGrow *instruction = ir_build_instruction<Stage1ZirInstWasmMemoryGrow>(ag, scope, source_node);
2884 instruction->index = index;
2885 instruction->delta = delta;
2886
2887 ir_ref_instruction(index, ag->current_basic_block);
2888 ir_ref_instruction(delta, ag->current_basic_block);
2889
2890 return &instruction->base;
2891}
2892
2893static Stage1ZirInst *ir_build_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
2894 Stage1ZirInstSrc *instruction = ir_build_instruction<Stage1ZirInstSrc>(ag, scope, source_node);
2895
2896 return &instruction->base;
2897}
2898
2899static Stage1ZirInst *ir_build_prefetch(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2900 Stage1ZirInst *ptr, Stage1ZirInst *options)
2901{
2902 Stage1ZirInstPrefetch *prefetch_instruction = ir_build_instruction<Stage1ZirInstPrefetch>(
2903 ag, scope, source_node);
2904 prefetch_instruction->ptr = ptr;
2905 prefetch_instruction->options = options;
2906
2907 ir_ref_instruction(ptr, ag->current_basic_block);
2908 ir_ref_instruction(options, ag->current_basic_block);
2909
2910 return &prefetch_instruction->base;
2911}
2912
2913
2914static void ir_count_defers(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_scope, size_t *results) {
2915 results[ReturnKindUnconditional] = 0;
2916 results[ReturnKindError] = 0;
2917
2918 Scope *scope = inner_scope;
2919
2920 while (scope != outer_scope) {
2921 assert(scope);
2922 switch (scope->id) {
2923 case ScopeIdDefer: {
2924 AstNode *defer_node = scope->source_node;
2925 assert(defer_node->type == NodeTypeDefer);
2926 ReturnKind defer_kind = defer_node->data.defer.kind;
2927 results[defer_kind] += 1;
2928 scope = scope->parent;
2929 continue;
2930 }
2931 case ScopeIdDecls:
2932 case ScopeIdFnDef:
2933 return;
2934 case ScopeIdBlock:
2935 case ScopeIdVarDecl:
2936 case ScopeIdLoop:
2937 case ScopeIdSuspend:
2938 case ScopeIdCompTime:
2939 case ScopeIdNoSuspend:
2940 case ScopeIdRuntime:
2941 case ScopeIdTypeOf:
2942 case ScopeIdExpr:
2943 scope = scope->parent;
2944 continue;
2945 case ScopeIdDeferExpr:
2946 case ScopeIdCImport:
2947 zig_unreachable();
2948 }
2949 }
2950}
2951
2952static bool astgen_defers_for_block(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_scope, bool *is_noreturn, Stage1ZirInst *err_value) {
2953 Scope *scope = inner_scope;
2954 if (is_noreturn != nullptr) *is_noreturn = false;
2955 while (scope != outer_scope) {
2956 if (!scope)
2957 return true;
2958
2959 switch (scope->id) {
2960 case ScopeIdDefer: {
2961 AstNode *defer_node = scope->source_node;
2962 assert(defer_node->type == NodeTypeDefer);
2963 ReturnKind defer_kind = defer_node->data.defer.kind;
2964 AstNode *defer_expr_node = defer_node->data.defer.expr;
2965 AstNode *defer_var_node = defer_node->data.defer.err_payload;
2966
2967 if (defer_kind == ReturnKindError && err_value == nullptr) {
2968 // This is an `errdefer` but we're generating code for a
2969 // `return` that doesn't return an error, skip it
2970 scope = scope->parent;
2971 continue;
2972 }
2973
2974 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
2975 if (defer_var_node != nullptr) {
2976 assert(defer_kind == ReturnKindError);
2977 assert(defer_var_node->type == NodeTypeIdentifier);
2978 Buf *var_name = node_identifier_buf(defer_var_node);
2979
2980 if (defer_expr_node->type == NodeTypeUnreachable) {
2981 add_node_error(ag->codegen, defer_var_node,
2982 buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
2983 return false;
2984 }
2985
2986 Stage1ZirInst *is_comptime;
2987 if (ir_should_inline(ag->exec, defer_expr_scope)) {
2988 is_comptime = ir_build_const_bool(ag, defer_expr_scope,
2989 defer_expr_node, true);
2990 } else {
2991 is_comptime = ir_build_test_comptime(ag, defer_expr_scope,
2992 defer_expr_node, err_value);
2993 }
2994
2995 ZigVar *err_var = ir_create_var(ag, defer_var_node, defer_expr_scope,
2996 var_name, true, true, false, is_comptime);
2997 build_decl_var_and_init(ag, defer_expr_scope, defer_var_node, err_var, err_value,
2998 buf_ptr(var_name), is_comptime);
2999
3000 defer_expr_scope = err_var->child_scope;
3001 }
3002
3003 Stage1ZirInst *defer_expr_value = astgen_node(ag, defer_expr_node, defer_expr_scope);
3004 if (defer_expr_value == ag->codegen->invalid_inst_src)
3005 return ag->codegen->invalid_inst_src;
3006
3007 if (instr_is_unreachable(defer_expr_value)) {
3008 if (is_noreturn != nullptr) *is_noreturn = true;
3009 } else {
3010 ir_build_check_statement_is_void(ag, defer_expr_scope, defer_expr_node,
3011 defer_expr_value);
3012 }
3013 scope = scope->parent;
3014 continue;
3015 }
3016 case ScopeIdDecls:
3017 case ScopeIdFnDef:
3018 return true;
3019 case ScopeIdBlock:
3020 case ScopeIdVarDecl:
3021 case ScopeIdLoop:
3022 case ScopeIdSuspend:
3023 case ScopeIdCompTime:
3024 case ScopeIdNoSuspend:
3025 case ScopeIdRuntime:
3026 case ScopeIdTypeOf:
3027 case ScopeIdExpr:
3028 scope = scope->parent;
3029 continue;
3030 case ScopeIdDeferExpr:
3031 case ScopeIdCImport:
3032 zig_unreachable();
3033 }
3034 }
3035 return true;
3036}
3037
3038static void ir_set_cursor_at_end(Stage1AstGen *ag, Stage1ZirBasicBlock *basic_block) {
3039 assert(basic_block);
3040 ag->current_basic_block = basic_block;
3041}
3042
3043static void ir_set_cursor_at_end_and_append_block(Stage1AstGen *ag, Stage1ZirBasicBlock *basic_block) {
3044 basic_block->index = ag->exec->basic_block_list.length;
3045 ag->exec->basic_block_list.append(basic_block);
3046 ir_set_cursor_at_end(ag, basic_block);
3047}
3048
3049static ScopeSuspend *get_scope_suspend(Scope *scope) {
3050 while (scope) {
3051 if (scope->id == ScopeIdSuspend)
3052 return (ScopeSuspend *)scope;
3053 if (scope->id == ScopeIdFnDef)
3054 return nullptr;
3055
3056 scope = scope->parent;
3057 }
3058 return nullptr;
3059}
3060
3061static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) {
3062 while (scope) {
3063 if (scope->id == ScopeIdDeferExpr)
3064 return (ScopeDeferExpr *)scope;
3065 if (scope->id == ScopeIdFnDef)
3066 return nullptr;
3067
3068 scope = scope->parent;
3069 }
3070 return nullptr;
3071}
3072
3073static Stage1ZirInst *astgen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
3074 assert(node->type == NodeTypeReturnExpr);
3075
3076 ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(scope);
3077 if (scope_defer_expr) {
3078 if (!scope_defer_expr->reported_err) {
3079 add_node_error(ag->codegen, node, buf_sprintf("cannot return from defer expression"));
3080 scope_defer_expr->reported_err = true;
3081 }
3082 return ag->codegen->invalid_inst_src;
3083 }
3084
3085 Scope *outer_scope = ag->exec->begin_scope;
3086
3087 AstNode *expr_node = node->data.return_expr.expr;
3088 switch (node->data.return_expr.kind) {
3089 case ReturnKindUnconditional:
3090 {
3091 ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>();
3092 result_loc_ret->base.id = ResultLocIdReturn;
3093 ir_build_reset_result(ag, scope, node, &result_loc_ret->base);
3094
3095 Stage1ZirInst *return_value;
3096 if (expr_node) {
3097 // Temporarily set this so that if we return a type it gets the name of the function
3098 ZigFn *prev_name_fn = ag->exec->name_fn;
3099 ag->exec->name_fn = ag->fn;
3100 return_value = astgen_node_extra(ag, expr_node, scope, LValNone, &result_loc_ret->base);
3101 ag->exec->name_fn = prev_name_fn;
3102 if (return_value == ag->codegen->invalid_inst_src)
3103 return ag->codegen->invalid_inst_src;
3104 } else {
3105 return_value = ir_build_const_void(ag, scope, node);
3106 ir_build_end_expr(ag, scope, node, return_value, &result_loc_ret->base);
3107 }
3108
3109 ir_build_add_implicit_return_type(ag, scope, node, return_value, result_loc_ret);
3110
3111 size_t defer_counts[2];
3112 ir_count_defers(ag, scope, outer_scope, defer_counts);
3113 bool have_err_defers = defer_counts[ReturnKindError] > 0;
3114 if (!have_err_defers && !ag->codegen->have_err_ret_tracing) {
3115 // only generate unconditional defers
3116 if (!astgen_defers_for_block(ag, scope, outer_scope, nullptr, nullptr))
3117 return ag->codegen->invalid_inst_src;
3118 Stage1ZirInst *result = ir_build_return_src(ag, scope, node, nullptr);
3119 result_loc_ret->base.source_instruction = result;
3120 return result;
3121 }
3122 bool should_inline = ir_should_inline(ag->exec, scope);
3123
3124 Stage1ZirBasicBlock *err_block = ir_create_basic_block(ag, scope, "ErrRetErr");
3125 Stage1ZirBasicBlock *ok_block = ir_create_basic_block(ag, scope, "ErrRetOk");
3126
3127 Stage1ZirInst *is_err = ir_build_test_err_src(ag, scope, node, return_value, false, true);
3128
3129 Stage1ZirInst *is_comptime;
3130 if (should_inline) {
3131 is_comptime = ir_build_const_bool(ag, scope, node, should_inline);
3132 } else {
3133 is_comptime = ir_build_test_comptime(ag, scope, node, is_err);
3134 }
3135
3136 ir_build_cond_br(ag, scope, node, is_err, err_block, ok_block, is_comptime);
3137 Stage1ZirBasicBlock *ret_stmt_block = ir_create_basic_block(ag, scope, "RetStmt");
3138
3139 ir_set_cursor_at_end_and_append_block(ag, err_block);
3140 if (!astgen_defers_for_block(ag, scope, outer_scope, nullptr, return_value))
3141 return ag->codegen->invalid_inst_src;
3142 if (ag->codegen->have_err_ret_tracing && !should_inline) {
3143 ir_build_save_err_ret_addr_src(ag, scope, node);
3144 }
3145 ir_build_br(ag, scope, node, ret_stmt_block, is_comptime);
3146
3147 ir_set_cursor_at_end_and_append_block(ag, ok_block);
3148 if (!astgen_defers_for_block(ag, scope, outer_scope, nullptr, nullptr))
3149 return ag->codegen->invalid_inst_src;
3150 ir_build_br(ag, scope, node, ret_stmt_block, is_comptime);
3151
3152 ir_set_cursor_at_end_and_append_block(ag, ret_stmt_block);
3153 Stage1ZirInst *result = ir_build_return_src(ag, scope, node, nullptr);
3154 result_loc_ret->base.source_instruction = result;
3155 return result;
3156 }
3157 case ReturnKindError:
3158 {
3159 assert(expr_node);
3160 Stage1ZirInst *err_union_ptr = astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr);
3161 if (err_union_ptr == ag->codegen->invalid_inst_src)
3162 return ag->codegen->invalid_inst_src;
3163 Stage1ZirInst *is_err_val = ir_build_test_err_src(ag, scope, node, err_union_ptr, true, false);
3164
3165 Stage1ZirBasicBlock *return_block = ir_create_basic_block(ag, scope, "ErrRetReturn");
3166 Stage1ZirBasicBlock *continue_block = ir_create_basic_block(ag, scope, "ErrRetContinue");
3167 Stage1ZirInst *is_comptime;
3168 bool should_inline = ir_should_inline(ag->exec, scope);
3169 if (should_inline) {
3170 is_comptime = ir_build_const_bool(ag, scope, node, true);
3171 } else {
3172 is_comptime = ir_build_test_comptime(ag, scope, node, is_err_val);
3173 }
3174 ir_build_cond_br(ag, scope, node, is_err_val, return_block, continue_block, is_comptime);
3175
3176 ir_set_cursor_at_end_and_append_block(ag, return_block);
3177 Stage1ZirInst *err_val_ptr = ir_build_unwrap_err_code_src(ag, scope, node, err_union_ptr);
3178 Stage1ZirInst *err_val = ir_build_load_ptr(ag, scope, node, err_val_ptr);
3179 ir_build_add_implicit_return_type(ag, scope, node, err_val, nullptr);
3180 Stage1ZirInstSpillBegin *spill_begin = ir_build_spill_begin_src(ag, scope, node, err_val,
3181 SpillIdRetErrCode);
3182 ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>();
3183 result_loc_ret->base.id = ResultLocIdReturn;
3184 ir_build_reset_result(ag, scope, node, &result_loc_ret->base);
3185 ir_build_end_expr(ag, scope, node, err_val, &result_loc_ret->base);
3186
3187 bool is_noreturn = false;
3188 if (!astgen_defers_for_block(ag, scope, outer_scope, &is_noreturn, err_val)) {
3189 return ag->codegen->invalid_inst_src;
3190 }
3191 if (!is_noreturn) {
3192 if (ag->codegen->have_err_ret_tracing && !should_inline) {
3193 ir_build_save_err_ret_addr_src(ag, scope, node);
3194 }
3195 err_val = ir_build_spill_end_src(ag, scope, node, spill_begin);
3196 Stage1ZirInst *ret_inst = ir_build_return_src(ag, scope, node, err_val);
3197 result_loc_ret->base.source_instruction = ret_inst;
3198 }
3199
3200 ir_set_cursor_at_end_and_append_block(ag, continue_block);
3201 Stage1ZirInst *unwrapped_ptr = ir_build_unwrap_err_payload_src(ag, scope, node, err_union_ptr, false, false);
3202 if (lval == LValPtr)
3203 return unwrapped_ptr;
3204 else
3205 return ir_expr_wrap(ag, scope, ir_build_load_ptr(ag, scope, node, unwrapped_ptr), result_loc);
3206 }
3207 }
3208 zig_unreachable();
3209}
3210
3211ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope,
3212 Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, Stage1ZirInst *is_comptime,
3213 bool skip_name_check)
3214{
3215 ZigVar *variable_entry = heap::c_allocator.create<ZigVar>();
3216 variable_entry->parent_scope = parent_scope;
3217 variable_entry->shadowable = is_shadowable;
3218 variable_entry->is_comptime = is_comptime;
3219 variable_entry->src_arg_index = SIZE_MAX;
3220 variable_entry->const_value = codegen->pass1_arena->create<ZigValue>();
3221
3222 if (is_comptime != nullptr) {
3223 is_comptime->ref_count += 1;
3224 }
3225
3226 if (name) {
3227 variable_entry->name = strdup(buf_ptr(name));
3228
3229 if (!skip_name_check) {
3230 ZigVar *existing_var = find_variable(codegen, parent_scope, name, nullptr);
3231 if (existing_var && !existing_var->shadowable) {
3232 if (existing_var->var_type == nullptr || !type_is_invalid(existing_var->var_type)) {
3233 ErrorMsg *msg = add_node_error(codegen, node,
3234 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3235 add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration here"));
3236 }
3237 variable_entry->var_type = codegen->builtin_types.entry_invalid;
3238 }
3239 }
3240 } else {
3241 assert(is_shadowable);
3242 // TODO make this name not actually be in scope. user should be able to make a variable called "_anon"
3243 // might already be solved, let's just make sure it has test coverage
3244 // maybe we put a prefix on this so the debug info doesn't clobber user debug info for same named variables
3245 variable_entry->name = "_anon";
3246 }
3247
3248 variable_entry->src_is_const = src_is_const;
3249 variable_entry->gen_is_const = gen_is_const;
3250 variable_entry->decl_node = node;
3251 variable_entry->child_scope = create_var_scope(codegen, node, parent_scope, variable_entry);
3252
3253 return variable_entry;
3254}
3255
3256
3257// Set name to nullptr to make the variable anonymous (not visible to programmer).
3258// After you call this function var->child_scope has the variable in scope
3259static ZigVar *ir_create_var(Stage1AstGen *ag, AstNode *node, Scope *scope, Buf *name,
3260 bool src_is_const, bool gen_is_const, bool is_shadowable, Stage1ZirInst *is_comptime)
3261{
3262 bool is_underscored = name ? buf_eql_str(name, "_") : false;
3263 ZigVar *var = create_local_var(ag->codegen, node, scope,
3264 (is_underscored ? nullptr : name), src_is_const, gen_is_const,
3265 (is_underscored ? true : is_shadowable), is_comptime, false);
3266 assert(var->child_scope);
3267 return var;
3268}
3269
3270static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) {
3271 ResultLocPeer *result = heap::c_allocator.create<ResultLocPeer>();
3272 result->base.id = ResultLocIdPeer;
3273 result->base.source_instruction = peer_parent->base.source_instruction;
3274 result->parent = peer_parent;
3275 result->base.allow_write_through_const = peer_parent->parent->allow_write_through_const;
3276 return result;
3277}
3278
3279static bool is_duplicate_label(CodeGen *g, Scope *scope, AstNode *node, Buf *name) {
3280 if (name == nullptr) return false;
3281
3282 for (;;) {
3283 if (scope == nullptr || scope->id == ScopeIdFnDef) {
3284 break;
3285 } else if (scope->id == ScopeIdBlock || scope->id == ScopeIdLoop) {
3286 Buf *this_block_name = scope->id == ScopeIdBlock ? ((ScopeBlock *)scope)->name : ((ScopeLoop *)scope)->name;
3287 if (this_block_name != nullptr && buf_eql_buf(name, this_block_name)) {
3288 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("redeclaration of label '%s'", buf_ptr(name)));
3289 add_error_note(g, msg, scope->source_node, buf_sprintf("previous declaration here"));
3290 return true;
3291 }
3292 }
3293 scope = scope->parent;
3294 }
3295 return false;
3296}
3297
3298static Stage1ZirInst *astgen_block(Stage1AstGen *ag, Scope *parent_scope, AstNode *block_node, LVal lval,
3299 ResultLoc *result_loc)
3300{
3301 assert(block_node->type == NodeTypeBlock);
3302
3303 ZigList<Stage1ZirInst *> incoming_values = {0};
3304 ZigList<Stage1ZirBasicBlock *> incoming_blocks = {0};
3305
3306 if (is_duplicate_label(ag->codegen, parent_scope, block_node, block_node->data.block.name))
3307 return ag->codegen->invalid_inst_src;
3308
3309 ScopeBlock *scope_block = create_block_scope(ag->codegen, block_node, parent_scope);
3310
3311 Scope *outer_block_scope = &scope_block->base;
3312 Scope *child_scope = outer_block_scope;
3313
3314 ZigFn *fn_entry = scope_fn_entry(parent_scope);
3315 if (fn_entry && fn_entry->child_scope == parent_scope) {
3316 fn_entry->def_scope = scope_block;
3317 }
3318
3319 if (block_node->data.block.statements.length == 0) {
3320 if (scope_block->name != nullptr) {
3321 add_node_error(ag->codegen, block_node, buf_sprintf("unused block label"));
3322 }
3323 // {}
3324 return ir_lval_wrap(ag, parent_scope, ir_build_const_void(ag, child_scope, block_node), lval, result_loc);
3325 }
3326
3327 if (block_node->data.block.name != nullptr) {
3328 scope_block->lval = lval;
3329 scope_block->incoming_blocks = &incoming_blocks;
3330 scope_block->incoming_values = &incoming_values;
3331 scope_block->end_block = ir_create_basic_block(ag, parent_scope, "BlockEnd");
3332 scope_block->is_comptime = ir_build_const_bool(ag, parent_scope, block_node,
3333 ir_should_inline(ag->exec, parent_scope));
3334
3335 scope_block->peer_parent = heap::c_allocator.create<ResultLocPeerParent>();
3336 scope_block->peer_parent->base.id = ResultLocIdPeerParent;
3337 scope_block->peer_parent->base.source_instruction = scope_block->is_comptime;
3338 scope_block->peer_parent->base.allow_write_through_const = result_loc->allow_write_through_const;
3339 scope_block->peer_parent->end_bb = scope_block->end_block;
3340 scope_block->peer_parent->is_comptime = scope_block->is_comptime;
3341 scope_block->peer_parent->parent = result_loc;
3342 ir_build_reset_result(ag, parent_scope, block_node, &scope_block->peer_parent->base);
3343 }
3344
3345 bool is_continuation_unreachable = false;
3346 bool found_invalid_inst = false;
3347 Stage1ZirInst *noreturn_return_value = nullptr;
3348 for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) {
3349 AstNode *statement_node = block_node->data.block.statements.at(i);
3350
3351 Stage1ZirInst *statement_value = astgen_node(ag, statement_node, child_scope);
3352 if (statement_value == ag->codegen->invalid_inst_src) {
3353 // keep generating all the elements of the block in case of error,
3354 // we want to collect other compile errors
3355 found_invalid_inst = true;
3356 continue;
3357 }
3358
3359 is_continuation_unreachable = instr_is_unreachable(statement_value);
3360 if (is_continuation_unreachable) {
3361 // keep the last noreturn statement value around in case we need to return it
3362 noreturn_return_value = statement_value;
3363 }
3364 // This logic must be kept in sync with
3365 // [STMT_EXPR_TEST_THING] <--- (search this token)
3366 if (statement_node->type == NodeTypeDefer) {
3367 // defer starts a new scope
3368 child_scope = statement_node->data.defer.child_scope;
3369 assert(child_scope);
3370 } else if (statement_value->id == Stage1ZirInstIdDeclVar) {
3371 // variable declarations start a new scope
3372 Stage1ZirInstDeclVar *decl_var_instruction = (Stage1ZirInstDeclVar *)statement_value;
3373 child_scope = decl_var_instruction->var->child_scope;
3374 } else if (!is_continuation_unreachable) {
3375 // this statement's value must be void
3376 ir_build_check_statement_is_void(ag, child_scope, statement_node, statement_value);
3377 }
3378 }
3379
3380 if (scope_block->name != nullptr && scope_block->name_used == false) {
3381 add_node_error(ag->codegen, block_node, buf_sprintf("unused block label"));
3382 }
3383
3384 if (found_invalid_inst)
3385 return ag->codegen->invalid_inst_src;
3386
3387 if (is_continuation_unreachable) {
3388 assert(noreturn_return_value != nullptr);
3389 if (block_node->data.block.name == nullptr || incoming_blocks.length == 0) {
3390 return noreturn_return_value;
3391 }
3392
3393 if (scope_block->peer_parent != nullptr && scope_block->peer_parent->peers.length != 0) {
3394 scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block;
3395 }
3396 ir_set_cursor_at_end_and_append_block(ag, scope_block->end_block);
3397 Stage1ZirInst *phi = ir_build_phi(ag, parent_scope, block_node, false, incoming_blocks.length,
3398 incoming_blocks.items, incoming_values.items, scope_block->peer_parent);
3399 return ir_expr_wrap(ag, parent_scope, phi, result_loc);
3400 } else {
3401 incoming_blocks.append(ag->current_basic_block);
3402 Stage1ZirInst *else_expr_result = ir_build_const_void(ag, parent_scope, block_node);
3403
3404 if (scope_block->peer_parent != nullptr) {
3405 ResultLocPeer *peer_result = create_peer_result(scope_block->peer_parent);
3406 scope_block->peer_parent->peers.append(peer_result);
3407 ir_build_end_expr(ag, parent_scope, block_node, else_expr_result, &peer_result->base);
3408
3409 if (scope_block->peer_parent->peers.length != 0) {
3410 scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block;
3411 }
3412 }
3413
3414 incoming_values.append(else_expr_result);
3415 }
3416
3417 bool is_return_from_fn = block_node == ag->main_block_node;
3418 if (!is_return_from_fn) {
3419 if (!astgen_defers_for_block(ag, child_scope, outer_block_scope, nullptr, nullptr))
3420 return ag->codegen->invalid_inst_src;
3421 }
3422
3423 Stage1ZirInst *result;
3424 if (block_node->data.block.name != nullptr) {
3425 ir_build_br(ag, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime);
3426 ir_set_cursor_at_end_and_append_block(ag, scope_block->end_block);
3427 Stage1ZirInst *phi = ir_build_phi(ag, parent_scope, block_node, false, incoming_blocks.length,
3428 incoming_blocks.items, incoming_values.items, scope_block->peer_parent);
3429 result = ir_expr_wrap(ag, parent_scope, phi, result_loc);
3430 } else {
3431 Stage1ZirInst *void_inst = ir_build_const_void(ag, child_scope, block_node);
3432 result = ir_lval_wrap(ag, parent_scope, void_inst, lval, result_loc);
3433 }
3434 if (!is_return_from_fn)
3435 return result;
3436
3437 // no need for save_err_ret_addr because this cannot return error
3438 // only generate unconditional defers
3439
3440 ir_build_add_implicit_return_type(ag, child_scope, block_node, result, nullptr);
3441 ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>();
3442 result_loc_ret->base.id = ResultLocIdReturn;
3443 ir_build_reset_result(ag, parent_scope, block_node, &result_loc_ret->base);
3444 ir_build_end_expr(ag, parent_scope, block_node, result, &result_loc_ret->base);
3445 if (!astgen_defers_for_block(ag, child_scope, outer_block_scope, nullptr, nullptr))
3446 return ag->codegen->invalid_inst_src;
3447 return ir_build_return_src(ag, child_scope, result->source_node, result);
3448}
3449
3450static Stage1ZirInst *astgen_bin_op_id(Stage1AstGen *ag, Scope *scope, AstNode *node, IrBinOp op_id) {
3451 Scope *inner_scope = scope;
3452 if (op_id == IrBinOpArrayCat || op_id == IrBinOpArrayMult) {
3453 inner_scope = create_comptime_scope(ag->codegen, node, scope);
3454 }
3455
3456 Stage1ZirInst *op1 = astgen_node(ag, node->data.bin_op_expr.op1, inner_scope);
3457 Stage1ZirInst *op2 = astgen_node(ag, node->data.bin_op_expr.op2, inner_scope);
3458
3459 if (op1 == ag->codegen->invalid_inst_src || op2 == ag->codegen->invalid_inst_src)
3460 return ag->codegen->invalid_inst_src;
3461
3462 return ir_build_bin_op(ag, scope, node, op_id, op1, op2, true);
3463}
3464
3465static Stage1ZirInst *astgen_merge_err_sets(Stage1AstGen *ag, Scope *scope, AstNode *node) {
3466 Stage1ZirInst *op1 = astgen_node(ag, node->data.bin_op_expr.op1, scope);
3467 Stage1ZirInst *op2 = astgen_node(ag, node->data.bin_op_expr.op2, scope);
3468
3469 if (op1 == ag->codegen->invalid_inst_src || op2 == ag->codegen->invalid_inst_src)
3470 return ag->codegen->invalid_inst_src;
3471
3472 // TODO only pass type_name when the || operator is the top level AST node in the var decl expr
3473 Buf bare_name = BUF_INIT;
3474 Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", scope, node, &bare_name, nullptr);
3475
3476 return ir_build_merge_err_sets(ag, scope, node, op1, op2, type_name);
3477}
3478
3479static Stage1ZirInst *astgen_assign(Stage1AstGen *ag, Scope *scope, AstNode *node) {
3480 Stage1ZirInst *lvalue = astgen_node_extra(ag, node->data.bin_op_expr.op1, scope, LValAssign, nullptr);
3481 if (lvalue == ag->codegen->invalid_inst_src)
3482 return ag->codegen->invalid_inst_src;
3483
3484 ResultLocInstruction *result_loc_inst = heap::c_allocator.create<ResultLocInstruction>();
3485 result_loc_inst->base.id = ResultLocIdInstruction;
3486 result_loc_inst->base.source_instruction = lvalue;
3487 ir_ref_instruction(lvalue, ag->current_basic_block);
3488 ir_build_reset_result(ag, scope, node, &result_loc_inst->base);
3489
3490 Stage1ZirInst *rvalue = astgen_node_extra(ag, node->data.bin_op_expr.op2, scope, LValNone,
3491 &result_loc_inst->base);
3492 if (rvalue == ag->codegen->invalid_inst_src)
3493 return ag->codegen->invalid_inst_src;
3494
3495 return ir_build_const_void(ag, scope, node);
3496}
3497
3498static Stage1ZirInst *astgen_assign_op(Stage1AstGen *ag, Scope *scope, AstNode *node, IrBinOp op_id) {
3499 Stage1ZirInst *lvalue = astgen_node_extra(ag, node->data.bin_op_expr.op1, scope, LValAssign, nullptr);
3500 if (lvalue == ag->codegen->invalid_inst_src)
3501 return lvalue;
3502 Stage1ZirInst *op1 = ir_build_load_ptr(ag, scope, node->data.bin_op_expr.op1, lvalue);
3503 Stage1ZirInst *op2 = astgen_node(ag, node->data.bin_op_expr.op2, scope);
3504 if (op2 == ag->codegen->invalid_inst_src)
3505 return op2;
3506 Stage1ZirInst *result = ir_build_bin_op(ag, scope, node, op_id, op1, op2, true);
3507 ir_build_store_ptr(ag, scope, node, lvalue, result);
3508 return ir_build_const_void(ag, scope, node);
3509}
3510
3511static Stage1ZirInst *astgen_bool_or(Stage1AstGen *ag, Scope *scope, AstNode *node) {
3512 assert(node->type == NodeTypeBinOpExpr);
3513
3514 Stage1ZirInst *val1 = astgen_node(ag, node->data.bin_op_expr.op1, scope);
3515 if (val1 == ag->codegen->invalid_inst_src)
3516 return ag->codegen->invalid_inst_src;
3517 Stage1ZirBasicBlock *post_val1_block = ag->current_basic_block;
3518
3519 Stage1ZirInst *is_comptime;
3520 if (ir_should_inline(ag->exec, scope)) {
3521 is_comptime = ir_build_const_bool(ag, scope, node, true);
3522 } else {
3523 is_comptime = ir_build_test_comptime(ag, scope, node, val1);
3524 }
3525
3526 // block for when val1 == false
3527 Stage1ZirBasicBlock *false_block = ir_create_basic_block(ag, scope, "BoolOrFalse");
3528 // block for when val1 == true (don't even evaluate the second part)
3529 Stage1ZirBasicBlock *true_block = ir_create_basic_block(ag, scope, "BoolOrTrue");
3530
3531 Stage1ZirInst *val1_true = ir_build_const_bool(ag, scope, node, true);
3532 ir_build_cond_br(ag, scope, node, val1, true_block, false_block, is_comptime);
3533
3534 ir_set_cursor_at_end_and_append_block(ag, false_block);
3535 Stage1ZirInst *val2 = astgen_node(ag, node->data.bin_op_expr.op2, scope);
3536 if (val2 == ag->codegen->invalid_inst_src)
3537 return ag->codegen->invalid_inst_src;
3538 Stage1ZirBasicBlock *post_val2_block = ag->current_basic_block;
3539
3540 ir_build_br(ag, scope, node, true_block, is_comptime);
3541
3542 ir_set_cursor_at_end_and_append_block(ag, true_block);
3543
3544 Stage1ZirInst **incoming_values = heap::c_allocator.allocate<Stage1ZirInst *>(2);
3545 incoming_values[0] = val1_true;
3546 incoming_values[1] = val2;
3547 Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2);
3548 incoming_blocks[0] = post_val1_block;
3549 incoming_blocks[1] = post_val2_block;
3550
3551 const bool merge_comptime = true;
3552 return ir_build_phi(ag, scope, node, merge_comptime, 2, incoming_blocks, incoming_values, nullptr);
3553}
3554
3555static Stage1ZirInst *astgen_bool_and(Stage1AstGen *ag, Scope *scope, AstNode *node) {
3556 assert(node->type == NodeTypeBinOpExpr);
3557
3558 Stage1ZirInst *val1 = astgen_node(ag, node->data.bin_op_expr.op1, scope);
3559 if (val1 == ag->codegen->invalid_inst_src)
3560 return ag->codegen->invalid_inst_src;
3561 Stage1ZirBasicBlock *post_val1_block = ag->current_basic_block;
3562
3563 Stage1ZirInst *is_comptime;
3564 if (ir_should_inline(ag->exec, scope)) {
3565 is_comptime = ir_build_const_bool(ag, scope, node, true);
3566 } else {
3567 is_comptime = ir_build_test_comptime(ag, scope, node, val1);
3568 }
3569
3570 // block for when val1 == true
3571 Stage1ZirBasicBlock *true_block = ir_create_basic_block(ag, scope, "BoolAndTrue");
3572 // block for when val1 == false (don't even evaluate the second part)
3573 Stage1ZirBasicBlock *false_block = ir_create_basic_block(ag, scope, "BoolAndFalse");
3574
3575 Stage1ZirInst *val1_false = ir_build_const_bool(ag, scope, node, false);
3576 ir_build_cond_br(ag, scope, node, val1, true_block, false_block, is_comptime);
3577
3578 ir_set_cursor_at_end_and_append_block(ag, true_block);
3579 Stage1ZirInst *val2 = astgen_node(ag, node->data.bin_op_expr.op2, scope);
3580 if (val2 == ag->codegen->invalid_inst_src)
3581 return ag->codegen->invalid_inst_src;
3582 Stage1ZirBasicBlock *post_val2_block = ag->current_basic_block;
3583
3584 ir_build_br(ag, scope, node, false_block, is_comptime);
3585
3586 ir_set_cursor_at_end_and_append_block(ag, false_block);
3587
3588 Stage1ZirInst **incoming_values = heap::c_allocator.allocate<Stage1ZirInst *>(2);
3589 incoming_values[0] = val1_false;
3590 incoming_values[1] = val2;
3591 Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2);
3592 incoming_blocks[0] = post_val1_block;
3593 incoming_blocks[1] = post_val2_block;
3594
3595 const bool merge_comptime = true;
3596 return ir_build_phi(ag, scope, node, merge_comptime, 2, incoming_blocks, incoming_values, nullptr);
3597}
3598
3599static ResultLocPeerParent *ir_build_result_peers(Stage1AstGen *ag, Stage1ZirInst *cond_br_inst,
3600 Stage1ZirBasicBlock *end_block, ResultLoc *parent, Stage1ZirInst *is_comptime)
3601{
3602 ResultLocPeerParent *peer_parent = heap::c_allocator.create<ResultLocPeerParent>();
3603 peer_parent->base.id = ResultLocIdPeerParent;
3604 peer_parent->base.source_instruction = cond_br_inst;
3605 peer_parent->base.allow_write_through_const = parent->allow_write_through_const;
3606 peer_parent->end_bb = end_block;
3607 peer_parent->is_comptime = is_comptime;
3608 peer_parent->parent = parent;
3609
3610 Stage1ZirInst *popped_inst = ag->current_basic_block->instruction_list.pop();
3611 ir_assert(popped_inst == cond_br_inst, cond_br_inst);
3612
3613 ir_build_reset_result(ag, cond_br_inst->scope, cond_br_inst->source_node, &peer_parent->base);
3614 ag->current_basic_block->instruction_list.append(popped_inst);
3615
3616 return peer_parent;
3617}
3618
3619static ResultLocPeerParent *ir_build_binary_result_peers(Stage1AstGen *ag, Stage1ZirInst *cond_br_inst,
3620 Stage1ZirBasicBlock *else_block, Stage1ZirBasicBlock *end_block, ResultLoc *parent, Stage1ZirInst *is_comptime)
3621{
3622 ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, parent, is_comptime);
3623
3624 peer_parent->peers.append(create_peer_result(peer_parent));
3625 peer_parent->peers.last()->next_bb = else_block;
3626
3627 peer_parent->peers.append(create_peer_result(peer_parent));
3628 peer_parent->peers.last()->next_bb = end_block;
3629
3630 return peer_parent;
3631}
3632
3633static Stage1ZirInst *astgen_orelse(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval,
3634 ResultLoc *result_loc)
3635{
3636 assert(node->type == NodeTypeBinOpExpr);
3637
3638 AstNode *op1_node = node->data.bin_op_expr.op1;
3639 AstNode *op2_node = node->data.bin_op_expr.op2;
3640
3641 Stage1ZirInst *maybe_ptr = astgen_node_extra(ag, op1_node, parent_scope, LValPtr, nullptr);
3642 if (maybe_ptr == ag->codegen->invalid_inst_src)
3643 return ag->codegen->invalid_inst_src;
3644
3645 Stage1ZirInst *maybe_val = ir_build_load_ptr(ag, parent_scope, node, maybe_ptr);
3646 Stage1ZirInst *is_non_null = ir_build_test_non_null_src(ag, parent_scope, node, maybe_val);
3647
3648 Stage1ZirInst *is_comptime;
3649 if (ir_should_inline(ag->exec, parent_scope)) {
3650 is_comptime = ir_build_const_bool(ag, parent_scope, node, true);
3651 } else {
3652 is_comptime = ir_build_test_comptime(ag, parent_scope, node, is_non_null);
3653 }
3654
3655 Stage1ZirBasicBlock *ok_block = ir_create_basic_block(ag, parent_scope, "OptionalNonNull");
3656 Stage1ZirBasicBlock *null_block = ir_create_basic_block(ag, parent_scope, "OptionalNull");
3657 Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, parent_scope, "OptionalEnd");
3658 Stage1ZirInst *cond_br_inst = ir_build_cond_br(ag, parent_scope, node, is_non_null, ok_block, null_block, is_comptime);
3659
3660 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, ok_block, end_block,
3661 result_loc, is_comptime);
3662
3663 ir_set_cursor_at_end_and_append_block(ag, null_block);
3664 Stage1ZirInst *null_result = astgen_node_extra(ag, op2_node, parent_scope, LValNone,
3665 &peer_parent->peers.at(0)->base);
3666 if (null_result == ag->codegen->invalid_inst_src)
3667 return ag->codegen->invalid_inst_src;
3668 Stage1ZirBasicBlock *after_null_block = ag->current_basic_block;
3669 if (!instr_is_unreachable(null_result))
3670 ir_build_br(ag, parent_scope, node, end_block, is_comptime);
3671
3672 ir_set_cursor_at_end_and_append_block(ag, ok_block);
3673 Stage1ZirInst *unwrapped_ptr = ir_build_optional_unwrap_ptr(ag, parent_scope, node, maybe_ptr, false);
3674 Stage1ZirInst *unwrapped_payload = ir_build_load_ptr(ag, parent_scope, node, unwrapped_ptr);
3675 ir_build_end_expr(ag, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base);
3676 Stage1ZirBasicBlock *after_ok_block = ag->current_basic_block;
3677 ir_build_br(ag, parent_scope, node, end_block, is_comptime);
3678
3679 ir_set_cursor_at_end_and_append_block(ag, end_block);
3680 Stage1ZirInst **incoming_values = heap::c_allocator.allocate<Stage1ZirInst *>(2);
3681 incoming_values[0] = null_result;
3682 incoming_values[1] = unwrapped_payload;
3683 Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2);
3684 incoming_blocks[0] = after_null_block;
3685 incoming_blocks[1] = after_ok_block;
3686 Stage1ZirInst *phi = ir_build_phi(ag, parent_scope, node, false, 2, incoming_blocks, incoming_values, peer_parent);
3687 return ir_lval_wrap(ag, parent_scope, phi, lval, result_loc);
3688}
3689
3690static Stage1ZirInst *astgen_error_union(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) {
3691 assert(node->type == NodeTypeBinOpExpr);
3692
3693 AstNode *op1_node = node->data.bin_op_expr.op1;
3694 AstNode *op2_node = node->data.bin_op_expr.op2;
3695
3696 Stage1ZirInst *err_set = astgen_node(ag, op1_node, parent_scope);
3697 if (err_set == ag->codegen->invalid_inst_src)
3698 return ag->codegen->invalid_inst_src;
3699
3700 Stage1ZirInst *payload = astgen_node(ag, op2_node, parent_scope);
3701 if (payload == ag->codegen->invalid_inst_src)
3702 return ag->codegen->invalid_inst_src;
3703
3704 return ir_build_error_union(ag, parent_scope, node, err_set, payload);
3705}
3706
3707static Stage1ZirInst *astgen_bin_op(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
3708 assert(node->type == NodeTypeBinOpExpr);
3709
3710 BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
3711 switch (bin_op_type) {
3712 case BinOpTypeInvalid:
3713 zig_unreachable();
3714 case BinOpTypeAssign:
3715 return ir_lval_wrap(ag, scope, astgen_assign(ag, scope, node), lval, result_loc);
3716 case BinOpTypeAssignTimes:
3717 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpMult), lval, result_loc);
3718 case BinOpTypeAssignTimesWrap:
3719 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpMultWrap), lval, result_loc);
3720 case BinOpTypeAssignTimesSat:
3721 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpMultSat), lval, result_loc);
3722 case BinOpTypeAssignDiv:
3723 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpDivUnspecified), lval, result_loc);
3724 case BinOpTypeAssignMod:
3725 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpRemUnspecified), lval, result_loc);
3726 case BinOpTypeAssignPlus:
3727 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpAdd), lval, result_loc);
3728 case BinOpTypeAssignPlusWrap:
3729 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpAddWrap), lval, result_loc);
3730 case BinOpTypeAssignPlusSat:
3731 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpAddSat), lval, result_loc);
3732 case BinOpTypeAssignMinus:
3733 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpSub), lval, result_loc);
3734 case BinOpTypeAssignMinusWrap:
3735 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpSubWrap), lval, result_loc);
3736 case BinOpTypeAssignMinusSat:
3737 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpSubSat), lval, result_loc);
3738 case BinOpTypeAssignBitShiftLeft:
3739 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc);
3740 case BinOpTypeAssignBitShiftLeftSat:
3741 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpShlSat), lval, result_loc);
3742 case BinOpTypeAssignBitShiftRight:
3743 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc);
3744 case BinOpTypeAssignBitAnd:
3745 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBinAnd), lval, result_loc);
3746 case BinOpTypeAssignBitXor:
3747 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBinXor), lval, result_loc);
3748 case BinOpTypeAssignBitOr:
3749 return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBinOr), lval, result_loc);
3750 case BinOpTypeBoolOr:
3751 return ir_lval_wrap(ag, scope, astgen_bool_or(ag, scope, node), lval, result_loc);
3752 case BinOpTypeBoolAnd:
3753 return ir_lval_wrap(ag, scope, astgen_bool_and(ag, scope, node), lval, result_loc);
3754 case BinOpTypeCmpEq:
3755 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpEq), lval, result_loc);
3756 case BinOpTypeCmpNotEq:
3757 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpNotEq), lval, result_loc);
3758 case BinOpTypeCmpLessThan:
3759 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpLessThan), lval, result_loc);
3760 case BinOpTypeCmpGreaterThan:
3761 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpGreaterThan), lval, result_loc);
3762 case BinOpTypeCmpLessOrEq:
3763 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpLessOrEq), lval, result_loc);
3764 case BinOpTypeCmpGreaterOrEq:
3765 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpGreaterOrEq), lval, result_loc);
3766 case BinOpTypeBinOr:
3767 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBinOr), lval, result_loc);
3768 case BinOpTypeBinXor:
3769 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBinXor), lval, result_loc);
3770 case BinOpTypeBinAnd:
3771 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBinAnd), lval, result_loc);
3772 case BinOpTypeBitShiftLeft:
3773 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc);
3774 case BinOpTypeBitShiftLeftSat:
3775 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpShlSat), lval, result_loc);
3776 case BinOpTypeBitShiftRight:
3777 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc);
3778 case BinOpTypeAdd:
3779 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpAdd), lval, result_loc);
3780 case BinOpTypeAddWrap:
3781 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpAddWrap), lval, result_loc);
3782 case BinOpTypeAddSat:
3783 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpAddSat), lval, result_loc);
3784 case BinOpTypeSub:
3785 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpSub), lval, result_loc);
3786 case BinOpTypeSubWrap:
3787 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpSubWrap), lval, result_loc);
3788 case BinOpTypeSubSat:
3789 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpSubSat), lval, result_loc);
3790 case BinOpTypeMult:
3791 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpMult), lval, result_loc);
3792 case BinOpTypeMultWrap:
3793 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpMultWrap), lval, result_loc);
3794 case BinOpTypeMultSat:
3795 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpMultSat), lval, result_loc);
3796 case BinOpTypeDiv:
3797 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpDivUnspecified), lval, result_loc);
3798 case BinOpTypeMod:
3799 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpRemUnspecified), lval, result_loc);
3800 case BinOpTypeArrayCat:
3801 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpArrayCat), lval, result_loc);
3802 case BinOpTypeArrayMult:
3803 return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpArrayMult), lval, result_loc);
3804 case BinOpTypeMergeErrorSets:
3805 return ir_lval_wrap(ag, scope, astgen_merge_err_sets(ag, scope, node), lval, result_loc);
3806 case BinOpTypeUnwrapOptional:
3807 return astgen_orelse(ag, scope, node, lval, result_loc);
3808 case BinOpTypeErrorUnion:
3809 return ir_lval_wrap(ag, scope, astgen_error_union(ag, scope, node), lval, result_loc);
3810 }
3811 zig_unreachable();
3812}
3813
3814static Stage1ZirInst *astgen_int_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) {
3815 assert(node->type == NodeTypeIntLiteral);
3816
3817 RootStruct *root_struct = node->owner->data.structure.root_struct;
3818 BigInt bigint;
3819 token_number_literal_bigint(root_struct, &bigint, node->main_token);
3820 return ir_build_const_bigint(ag, scope, node, bigint);
3821}
3822
3823static Stage1ZirInst *astgen_float_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) {
3824 Error err;
3825 assert(node->type == NodeTypeFloatLiteral);
3826
3827 RootStruct *root_struct = node->owner->data.structure.root_struct;
3828 const char *source = buf_ptr(root_struct->source_code);
3829 uint32_t byte_offset = root_struct->token_locs[node->main_token].offset;
3830
3831 BigFloat bigfloat;
3832 if ((err = bigfloat_init_buf(&bigfloat, (const uint8_t *)source + byte_offset))) {
3833 add_node_error(ag->codegen, node, buf_sprintf("float literal out of range of any type"));
3834 return ag->codegen->invalid_inst_src;
3835 }
3836
3837 return ir_build_const_bigfloat(ag, scope, node, bigfloat);
3838}
3839
3840static Stage1ZirInst *astgen_char_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) {
3841 Error err;
3842 assert(node->type == NodeTypeCharLiteral);
3843
3844 RootStruct *root_struct = node->owner->data.structure.root_struct;
3845 const char *source = buf_ptr(root_struct->source_code);
3846 uint32_t byte_offset = root_struct->token_locs[node->main_token].offset;
3847
3848 src_assert(source[byte_offset] == '\'', node);
3849 byte_offset += 1;
3850
3851 uint32_t codepoint;
3852 size_t bad_index;
3853 if ((err = source_char_literal(source + byte_offset, &codepoint, &bad_index))) {
3854 add_node_error(ag->codegen, node, buf_sprintf("invalid character"));
3855 return ag->codegen->invalid_inst_src;
3856 }
3857 return ir_build_const_uint(ag, scope, node, codepoint);
3858}
3859
3860static Stage1ZirInst *astgen_identifier(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval,
3861 ResultLoc *result_loc)
3862{
3863 Error err;
3864 assert(node->type == NodeTypeIdentifier);
3865
3866 bool is_at_syntax;
3867 Buf *variable_name = node_identifier_buf2(node, &is_at_syntax);
3868
3869 if (!is_at_syntax) {
3870 if (buf_eql_str(variable_name, "_")) {
3871 if (lval == LValAssign) {
3872 Stage1ZirInstConst *const_instruction = ir_build_instruction<Stage1ZirInstConst>(ag, scope, node);
3873 const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>();
3874 const_instruction->value->type = get_pointer_to_type(ag->codegen,
3875 ag->codegen->builtin_types.entry_void, false);
3876 const_instruction->value->special = ConstValSpecialStatic;
3877 const_instruction->value->data.x_ptr.special = ConstPtrSpecialDiscard;
3878 return &const_instruction->base;
3879 }
3880 }
3881
3882 {
3883 Stage1ZirInst *value = nullptr;
3884 if (buf_eql_str(variable_name, "null")) {
3885 value = ir_build_const_null(ag, scope, node);
3886 } else if (buf_eql_str(variable_name, "true")) {
3887 value = ir_build_const_bool(ag, scope, node, true);
3888 } else if (buf_eql_str(variable_name, "false")) {
3889 value = ir_build_const_bool(ag, scope, node, false);
3890 } else if (buf_eql_str(variable_name, "undefined")) {
3891 value = ir_build_const_undefined(ag, scope, node);
3892 }
3893
3894 if (value != nullptr) {
3895 if (lval == LValPtr || lval == LValAssign) {
3896 return ir_build_ref_src(ag, scope, node, value);
3897 } else {
3898 return ir_expr_wrap(ag, scope, value, result_loc);
3899 }
3900 }
3901 }
3902
3903 ZigType *primitive_type;
3904 if ((err = get_primitive_type(ag->codegen, variable_name, &primitive_type))) {
3905 if (err == ErrorOverflow) {
3906 add_node_error(ag->codegen, node,
3907 buf_sprintf("primitive integer type '%s' exceeds maximum bit width of 65535",
3908 buf_ptr(variable_name)));
3909 return ag->codegen->invalid_inst_src;
3910 }
3911 assert(err == ErrorPrimitiveTypeNotFound);
3912 } else {
3913 Stage1ZirInst *value = ir_build_const_type(ag, scope, node, primitive_type);
3914 if (lval == LValPtr || lval == LValAssign) {
3915 return ir_build_ref_src(ag, scope, node, value);
3916 } else {
3917 return ir_expr_wrap(ag, scope, value, result_loc);
3918 }
3919 }
3920 }
3921
3922 ScopeFnDef *crossed_fndef_scope;
3923 ZigVar *var = find_variable(ag->codegen, scope, variable_name, &crossed_fndef_scope);
3924 if (var) {
3925 Stage1ZirInst *var_ptr = ir_build_var_ptr_x(ag, scope, node, var, crossed_fndef_scope);
3926 if (lval == LValPtr || lval == LValAssign) {
3927 return var_ptr;
3928 } else {
3929 return ir_expr_wrap(ag, scope, ir_build_load_ptr(ag, scope, node, var_ptr), result_loc);
3930 }
3931 }
3932
3933 Tld *tld = nullptr;
3934 {
3935 Scope *s = scope;
3936 while (s) {
3937 if (s->id == ScopeIdDecls) {
3938 ScopeDecls *decls_scope = (ScopeDecls *)s;
3939
3940 Tld *result = find_container_decl(ag->codegen, decls_scope, variable_name);
3941 if (result != nullptr) {
3942 if (tld != nullptr && tld != result) {
3943 ErrorMsg *msg = add_node_error(ag->codegen, node,
3944 buf_sprintf("ambiguous reference"));
3945 add_error_note(ag->codegen, msg, tld->source_node,
3946 buf_sprintf("declared here"));
3947 add_error_note(ag->codegen, msg, result->source_node,
3948 buf_sprintf("also declared here"));
3949 return ag->codegen->invalid_inst_src;
3950 }
3951 tld = result;
3952 }
3953 }
3954 s = s->parent;
3955 }
3956 }
3957
3958 if (tld) {
3959 Stage1ZirInst *decl_ref = ir_build_decl_ref(ag, scope, node, tld, lval);
3960 if (lval == LValPtr || lval == LValAssign) {
3961 return decl_ref;
3962 } else {
3963 return ir_expr_wrap(ag, scope, decl_ref, result_loc);
3964 }
3965 }
3966
3967 if (get_container_scope(node->owner)->any_imports_failed) {
3968 // skip the error message since we had a failing import in this file
3969 // if an import breaks we don't need redundant undeclared identifier errors
3970 return ag->codegen->invalid_inst_src;
3971 }
3972
3973 return ir_build_undeclared_identifier(ag, scope, node, variable_name);
3974}
3975
3976static Stage1ZirInst *astgen_array_access(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval,
3977 ResultLoc *result_loc)
3978{
3979 assert(node->type == NodeTypeArrayAccessExpr);
3980
3981 AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr;
3982 Stage1ZirInst *array_ref_instruction = astgen_node_extra(ag, array_ref_node, scope, LValPtr, nullptr);
3983 if (array_ref_instruction == ag->codegen->invalid_inst_src)
3984 return array_ref_instruction;
3985
3986 // Create an usize-typed result location to hold the subscript value, this
3987 // makes it possible for the compiler to infer the subscript expression type
3988 // if needed
3989 Stage1ZirInst *usize_type_inst = ir_build_const_type(ag, scope, node, ag->codegen->builtin_types.entry_usize);
3990 ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, usize_type_inst, no_result_loc());
3991
3992 AstNode *subscript_node = node->data.array_access_expr.subscript;
3993 Stage1ZirInst *subscript_value = astgen_node_extra(ag, subscript_node, scope, LValNone, &result_loc_cast->base);
3994 if (subscript_value == ag->codegen->invalid_inst_src)
3995 return ag->codegen->invalid_inst_src;
3996
3997 Stage1ZirInst *subscript_instruction = ir_build_implicit_cast(ag, scope, subscript_node, subscript_value, result_loc_cast);
3998
3999 Stage1ZirInst *ptr_instruction = ir_build_elem_ptr(ag, scope, node, array_ref_instruction,
4000 subscript_instruction, true, PtrLenSingle, nullptr);
4001 if (lval == LValPtr || lval == LValAssign)
4002 return ptr_instruction;
4003
4004 Stage1ZirInst *load_ptr = ir_build_load_ptr(ag, scope, node, ptr_instruction);
4005 return ir_expr_wrap(ag, scope, load_ptr, result_loc);
4006}
4007
4008static Stage1ZirInst *astgen_field_access(Stage1AstGen *ag, Scope *scope, AstNode *node) {
4009 assert(node->type == NodeTypeFieldAccessExpr);
4010
4011 AstNode *container_ref_node = node->data.field_access_expr.struct_expr;
4012 Buf *field_name = node->data.field_access_expr.field_name;
4013
4014 Stage1ZirInst *container_ref_instruction = astgen_node_extra(ag, container_ref_node, scope, LValPtr, nullptr);
4015 if (container_ref_instruction == ag->codegen->invalid_inst_src)
4016 return container_ref_instruction;
4017
4018 return ir_build_field_ptr(ag, scope, node, container_ref_instruction, field_name, false);
4019}
4020
4021static Stage1ZirInst *astgen_overflow_op(Stage1AstGen *ag, Scope *scope, AstNode *node, IrOverflowOp op) {
4022 assert(node->type == NodeTypeFnCallExpr);
4023
4024 AstNode *type_node = node->data.fn_call_expr.params.at(0);
4025 AstNode *op1_node = node->data.fn_call_expr.params.at(1);
4026 AstNode *op2_node = node->data.fn_call_expr.params.at(2);
4027 AstNode *result_ptr_node = node->data.fn_call_expr.params.at(3);
4028
4029
4030 Stage1ZirInst *type_value = astgen_node(ag, type_node, scope);
4031 if (type_value == ag->codegen->invalid_inst_src)
4032 return ag->codegen->invalid_inst_src;
4033
4034 Stage1ZirInst *op1 = astgen_node(ag, op1_node, scope);
4035 if (op1 == ag->codegen->invalid_inst_src)
4036 return ag->codegen->invalid_inst_src;
4037
4038 Stage1ZirInst *op2 = astgen_node(ag, op2_node, scope);
4039 if (op2 == ag->codegen->invalid_inst_src)
4040 return ag->codegen->invalid_inst_src;
4041
4042 Stage1ZirInst *result_ptr = astgen_node(ag, result_ptr_node, scope);
4043 if (result_ptr == ag->codegen->invalid_inst_src)
4044 return ag->codegen->invalid_inst_src;
4045
4046 return ir_build_overflow_op_src(ag, scope, node, op, type_value, op1, op2, result_ptr);
4047}
4048
4049static Stage1ZirInst *astgen_mul_add(Stage1AstGen *ag, Scope *scope, AstNode *node) {
4050 assert(node->type == NodeTypeFnCallExpr);
4051
4052 AstNode *type_node = node->data.fn_call_expr.params.at(0);
4053 AstNode *op1_node = node->data.fn_call_expr.params.at(1);
4054 AstNode *op2_node = node->data.fn_call_expr.params.at(2);
4055 AstNode *op3_node = node->data.fn_call_expr.params.at(3);
4056
4057 Stage1ZirInst *type_value = astgen_node(ag, type_node, scope);
4058 if (type_value == ag->codegen->invalid_inst_src)
4059 return ag->codegen->invalid_inst_src;
4060
4061 Stage1ZirInst *op1 = astgen_node(ag, op1_node, scope);
4062 if (op1 == ag->codegen->invalid_inst_src)
4063 return ag->codegen->invalid_inst_src;
4064
4065 Stage1ZirInst *op2 = astgen_node(ag, op2_node, scope);
4066 if (op2 == ag->codegen->invalid_inst_src)
4067 return ag->codegen->invalid_inst_src;
4068
4069 Stage1ZirInst *op3 = astgen_node(ag, op3_node, scope);
4070 if (op3 == ag->codegen->invalid_inst_src)
4071 return ag->codegen->invalid_inst_src;
4072
4073 return ir_build_mul_add_src(ag, scope, node, type_value, op1, op2, op3);
4074}
4075
4076static Stage1ZirInst *astgen_this(Stage1AstGen *ag, Scope *orig_scope, AstNode *node) {
4077 for (Scope *it_scope = orig_scope; it_scope != nullptr; it_scope = it_scope->parent) {
4078 if (it_scope->id == ScopeIdDecls) {
4079 ScopeDecls *decls_scope = (ScopeDecls *)it_scope;
4080 ZigType *container_type = decls_scope->container_type;
4081 if (container_type != nullptr) {
4082 return ir_build_const_type(ag, orig_scope, node, container_type);
4083 } else {
4084 return ir_build_const_import(ag, orig_scope, node, decls_scope->import);
4085 }
4086 }
4087 }
4088 zig_unreachable();
4089}
4090
4091static Stage1ZirInst *astgen_async_call(Stage1AstGen *ag, Scope *scope, AstNode *await_node, AstNode *call_node,
4092 LVal lval, ResultLoc *result_loc)
4093{
4094 if (call_node->data.fn_call_expr.params.length != 4) {
4095 add_node_error(ag->codegen, call_node,
4096 buf_sprintf("expected 4 arguments, found %" ZIG_PRI_usize,
4097 call_node->data.fn_call_expr.params.length));
4098 return ag->codegen->invalid_inst_src;
4099 }
4100
4101 AstNode *bytes_node = call_node->data.fn_call_expr.params.at(0);
4102 Stage1ZirInst *bytes = astgen_node(ag, bytes_node, scope);
4103 if (bytes == ag->codegen->invalid_inst_src)
4104 return bytes;
4105
4106 AstNode *ret_ptr_node = call_node->data.fn_call_expr.params.at(1);
4107 Stage1ZirInst *ret_ptr = astgen_node(ag, ret_ptr_node, scope);
4108 if (ret_ptr == ag->codegen->invalid_inst_src)
4109 return ret_ptr;
4110
4111 AstNode *fn_ref_node = call_node->data.fn_call_expr.params.at(2);
4112 Stage1ZirInst *fn_ref = astgen_node(ag, fn_ref_node, scope);
4113 if (fn_ref == ag->codegen->invalid_inst_src)
4114 return fn_ref;
4115
4116 CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone;
4117 bool is_async_call_builtin = true;
4118 AstNode *args_node = call_node->data.fn_call_expr.params.at(3);
4119 if (args_node->type == NodeTypeContainerInitExpr) {
4120 if (args_node->data.container_init_expr.kind == ContainerInitKindArray ||
4121 args_node->data.container_init_expr.entries.length == 0)
4122 {
4123 size_t arg_count = args_node->data.container_init_expr.entries.length;
4124 Stage1ZirInst **args = heap::c_allocator.allocate<Stage1ZirInst*>(arg_count);
4125 for (size_t i = 0; i < arg_count; i += 1) {
4126 AstNode *arg_node = args_node->data.container_init_expr.entries.at(i);
4127 Stage1ZirInst *arg = astgen_node(ag, arg_node, scope);
4128 if (arg == ag->codegen->invalid_inst_src)
4129 return arg;
4130 args[i] = arg;
4131 }
4132
4133 Stage1ZirInst *call = ir_build_call_src(ag, scope, call_node, nullptr, fn_ref, arg_count, args,
4134 ret_ptr, modifier, is_async_call_builtin, bytes, result_loc);
4135 return ir_lval_wrap(ag, scope, call, lval, result_loc);
4136 } else {
4137 exec_add_error_node(ag->codegen, ag->exec, args_node,
4138 buf_sprintf("TODO: @asyncCall with anon struct literal"));
4139 return ag->codegen->invalid_inst_src;
4140 }
4141 }
4142 Stage1ZirInst *args = astgen_node(ag, args_node, scope);
4143 if (args == ag->codegen->invalid_inst_src)
4144 return args;
4145
4146 Stage1ZirInst *call = ir_build_async_call_extra(ag, scope, call_node, modifier, fn_ref, ret_ptr, bytes, args, result_loc);
4147 return ir_lval_wrap(ag, scope, call, lval, result_loc);
4148}
4149
4150static Stage1ZirInst *astgen_fn_call_with_args(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
4151 AstNode *fn_ref_node, CallModifier modifier, Stage1ZirInst *options,
4152 AstNode **args_ptr, size_t args_len, LVal lval, ResultLoc *result_loc)
4153{
4154 Stage1ZirInst *fn_ref = astgen_node(ag, fn_ref_node, scope);
4155 if (fn_ref == ag->codegen->invalid_inst_src)
4156 return fn_ref;
4157
4158 Stage1ZirInst *fn_type = ir_build_typeof_1(ag, scope, source_node, fn_ref);
4159
4160 Stage1ZirInst **args = heap::c_allocator.allocate<Stage1ZirInst*>(args_len);
4161 for (size_t i = 0; i < args_len; i += 1) {
4162 AstNode *arg_node = args_ptr[i];
4163
4164 Stage1ZirInst *arg_index = ir_build_const_usize(ag, scope, arg_node, i);
4165 Stage1ZirInst *arg_type = ir_build_arg_type(ag, scope, source_node, fn_type, arg_index, true);
4166 ResultLoc *no_result = no_result_loc();
4167 ir_build_reset_result(ag, scope, source_node, no_result);
4168 ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, arg_type, no_result);
4169
4170 Stage1ZirInst *arg = astgen_node_extra(ag, arg_node, scope, LValNone, &result_loc_cast->base);
4171 if (arg == ag->codegen->invalid_inst_src)
4172 return arg;
4173
4174 args[i] = ir_build_implicit_cast(ag, scope, arg_node, arg, result_loc_cast);
4175 }
4176
4177 Stage1ZirInst *fn_call;
4178 if (options != nullptr) {
4179 fn_call = ir_build_call_args(ag, scope, source_node, options, fn_ref, args, args_len, result_loc);
4180 } else {
4181 fn_call = ir_build_call_src(ag, scope, source_node, nullptr, fn_ref, args_len, args, nullptr,
4182 modifier, false, nullptr, result_loc);
4183 }
4184 return ir_lval_wrap(ag, scope, fn_call, lval, result_loc);
4185}
4186
4187static Stage1ZirInst *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval,
4188 ResultLoc *result_loc)
4189{
4190 assert(node->type == NodeTypeFnCallExpr);
4191
4192 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
4193 Buf *name = node_identifier_buf(fn_ref_expr);
4194 auto entry = ag->codegen->builtin_fn_table.maybe_get(name);
4195
4196 if (!entry) {
4197 add_node_error(ag->codegen, node,
4198 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
4199 return ag->codegen->invalid_inst_src;
4200 }
4201
4202 BuiltinFnEntry *builtin_fn = entry->value;
4203 size_t actual_param_count = node->data.fn_call_expr.params.length;
4204
4205 if (builtin_fn->param_count != SIZE_MAX && builtin_fn->param_count != actual_param_count) {
4206 add_node_error(ag->codegen, node,
4207 buf_sprintf("expected %" ZIG_PRI_usize " argument(s), found %" ZIG_PRI_usize,
4208 builtin_fn->param_count, actual_param_count));
4209 return ag->codegen->invalid_inst_src;
4210 }
4211
4212 switch (builtin_fn->id) {
4213 case BuiltinFnIdInvalid:
4214 zig_unreachable();
4215 case BuiltinFnIdTypeof:
4216 {
4217 Scope *sub_scope = create_typeof_scope(ag->codegen, node, scope);
4218
4219 size_t arg_count = node->data.fn_call_expr.params.length;
4220
4221 Stage1ZirInst *type_of;
4222
4223 if (arg_count == 0) {
4224 add_node_error(ag->codegen, node,
4225 buf_sprintf("expected at least 1 argument, found 0"));
4226 return ag->codegen->invalid_inst_src;
4227 } else if (arg_count == 1) {
4228 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4229 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, sub_scope);
4230 if (arg0_value == ag->codegen->invalid_inst_src)
4231 return arg0_value;
4232
4233 type_of = ir_build_typeof_1(ag, scope, node, arg0_value);
4234 } else {
4235 Stage1ZirInst **args = heap::c_allocator.allocate<Stage1ZirInst*>(arg_count);
4236 for (size_t i = 0; i < arg_count; i += 1) {
4237 AstNode *arg_node = node->data.fn_call_expr.params.at(i);
4238 Stage1ZirInst *arg = astgen_node(ag, arg_node, sub_scope);
4239 if (arg == ag->codegen->invalid_inst_src)
4240 return ag->codegen->invalid_inst_src;
4241 args[i] = arg;
4242 }
4243
4244 type_of = ir_build_typeof_n(ag, scope, node, args, arg_count);
4245 }
4246 return ir_lval_wrap(ag, scope, type_of, lval, result_loc);
4247 }
4248 case BuiltinFnIdSetCold:
4249 {
4250 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4251 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4252 if (arg0_value == ag->codegen->invalid_inst_src)
4253 return arg0_value;
4254
4255 Stage1ZirInst *set_cold = ir_build_set_cold(ag, scope, node, arg0_value);
4256 return ir_lval_wrap(ag, scope, set_cold, lval, result_loc);
4257 }
4258 case BuiltinFnIdSetRuntimeSafety:
4259 {
4260 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4261 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4262 if (arg0_value == ag->codegen->invalid_inst_src)
4263 return arg0_value;
4264
4265 Stage1ZirInst *set_safety = ir_build_set_runtime_safety(ag, scope, node, arg0_value);
4266 return ir_lval_wrap(ag, scope, set_safety, lval, result_loc);
4267 }
4268 case BuiltinFnIdSetFloatMode:
4269 {
4270 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4271 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4272 if (arg0_value == ag->codegen->invalid_inst_src)
4273 return arg0_value;
4274
4275 Stage1ZirInst *set_float_mode = ir_build_set_float_mode(ag, scope, node, arg0_value);
4276 return ir_lval_wrap(ag, scope, set_float_mode, lval, result_loc);
4277 }
4278 case BuiltinFnIdSizeof:
4279 case BuiltinFnIdBitSizeof:
4280 {
4281 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4282 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4283 if (arg0_value == ag->codegen->invalid_inst_src)
4284 return arg0_value;
4285
4286 Stage1ZirInst *size_of = ir_build_size_of(ag, scope, node, arg0_value, builtin_fn->id == BuiltinFnIdBitSizeof);
4287 return ir_lval_wrap(ag, scope, size_of, lval, result_loc);
4288 }
4289 case BuiltinFnIdImport:
4290 {
4291 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4292 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4293 if (arg0_value == ag->codegen->invalid_inst_src)
4294 return arg0_value;
4295
4296 Stage1ZirInst *import = ir_build_import(ag, scope, node, arg0_value);
4297 return ir_lval_wrap(ag, scope, import, lval, result_loc);
4298 }
4299 case BuiltinFnIdCImport:
4300 {
4301 Stage1ZirInst *c_import = ir_build_c_import(ag, scope, node);
4302 return ir_lval_wrap(ag, scope, c_import, lval, result_loc);
4303 }
4304 case BuiltinFnIdCInclude:
4305 {
4306 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4307 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4308 if (arg0_value == ag->codegen->invalid_inst_src)
4309 return arg0_value;
4310
4311 if (!ag->in_c_import_scope) {
4312 add_node_error(ag->codegen, node, buf_sprintf("C include valid only inside C import block"));
4313 return ag->codegen->invalid_inst_src;
4314 }
4315
4316 Stage1ZirInst *c_include = ir_build_c_include(ag, scope, node, arg0_value);
4317 return ir_lval_wrap(ag, scope, c_include, lval, result_loc);
4318 }
4319 case BuiltinFnIdCDefine:
4320 {
4321 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4322 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4323 if (arg0_value == ag->codegen->invalid_inst_src)
4324 return arg0_value;
4325
4326 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4327 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4328 if (arg1_value == ag->codegen->invalid_inst_src)
4329 return arg1_value;
4330
4331 if (!ag->in_c_import_scope) {
4332 add_node_error(ag->codegen, node, buf_sprintf("C define valid only inside C import block"));
4333 return ag->codegen->invalid_inst_src;
4334 }
4335
4336 Stage1ZirInst *c_define = ir_build_c_define(ag, scope, node, arg0_value, arg1_value);
4337 return ir_lval_wrap(ag, scope, c_define, lval, result_loc);
4338 }
4339 case BuiltinFnIdCUndef:
4340 {
4341 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4342 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4343 if (arg0_value == ag->codegen->invalid_inst_src)
4344 return arg0_value;
4345
4346 if (!ag->in_c_import_scope) {
4347 add_node_error(ag->codegen, node, buf_sprintf("C undef valid only inside C import block"));
4348 return ag->codegen->invalid_inst_src;
4349 }
4350
4351 Stage1ZirInst *c_undef = ir_build_c_undef(ag, scope, node, arg0_value);
4352 return ir_lval_wrap(ag, scope, c_undef, lval, result_loc);
4353 }
4354 case BuiltinFnIdCompileErr:
4355 {
4356 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4357 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4358 if (arg0_value == ag->codegen->invalid_inst_src)
4359 return arg0_value;
4360
4361 Stage1ZirInst *compile_err = ir_build_compile_err(ag, scope, node, arg0_value);
4362 return ir_lval_wrap(ag, scope, compile_err, lval, result_loc);
4363 }
4364 case BuiltinFnIdCompileLog:
4365 {
4366 Stage1ZirInst **args = heap::c_allocator.allocate<Stage1ZirInst*>(actual_param_count);
4367
4368 for (size_t i = 0; i < actual_param_count; i += 1) {
4369 AstNode *arg_node = node->data.fn_call_expr.params.at(i);
4370 args[i] = astgen_node(ag, arg_node, scope);
4371 if (args[i] == ag->codegen->invalid_inst_src)
4372 return ag->codegen->invalid_inst_src;
4373 }
4374
4375 Stage1ZirInst *compile_log = ir_build_compile_log(ag, scope, node, actual_param_count, args);
4376 return ir_lval_wrap(ag, scope, compile_log, lval, result_loc);
4377 }
4378 case BuiltinFnIdErrName:
4379 {
4380 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4381 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4382 if (arg0_value == ag->codegen->invalid_inst_src)
4383 return arg0_value;
4384
4385 Stage1ZirInst *err_name = ir_build_err_name(ag, scope, node, arg0_value);
4386 return ir_lval_wrap(ag, scope, err_name, lval, result_loc);
4387 }
4388 case BuiltinFnIdEmbedFile:
4389 {
4390 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4391 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4392 if (arg0_value == ag->codegen->invalid_inst_src)
4393 return arg0_value;
4394
4395 Stage1ZirInst *embed_file = ir_build_embed_file(ag, scope, node, arg0_value);
4396 return ir_lval_wrap(ag, scope, embed_file, lval, result_loc);
4397 }
4398 case BuiltinFnIdCmpxchgWeak:
4399 case BuiltinFnIdCmpxchgStrong:
4400 {
4401 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4402 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4403 if (arg0_value == ag->codegen->invalid_inst_src)
4404 return arg0_value;
4405
4406 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4407 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4408 if (arg1_value == ag->codegen->invalid_inst_src)
4409 return arg1_value;
4410
4411 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
4412 Stage1ZirInst *arg2_value = astgen_node(ag, arg2_node, scope);
4413 if (arg2_value == ag->codegen->invalid_inst_src)
4414 return arg2_value;
4415
4416 AstNode *arg3_node = node->data.fn_call_expr.params.at(3);
4417 Stage1ZirInst *arg3_value = astgen_node(ag, arg3_node, scope);
4418 if (arg3_value == ag->codegen->invalid_inst_src)
4419 return arg3_value;
4420
4421 AstNode *arg4_node = node->data.fn_call_expr.params.at(4);
4422 Stage1ZirInst *arg4_value = astgen_node(ag, arg4_node, scope);
4423 if (arg4_value == ag->codegen->invalid_inst_src)
4424 return arg4_value;
4425
4426 AstNode *arg5_node = node->data.fn_call_expr.params.at(5);
4427 Stage1ZirInst *arg5_value = astgen_node(ag, arg5_node, scope);
4428 if (arg5_value == ag->codegen->invalid_inst_src)
4429 return arg5_value;
4430
4431 Stage1ZirInst *cmpxchg = ir_build_cmpxchg_src(ag, scope, node, arg0_value, arg1_value,
4432 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak),
4433 result_loc);
4434 return ir_lval_wrap(ag, scope, cmpxchg, lval, result_loc);
4435 }
4436 case BuiltinFnIdFence:
4437 {
4438 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4439 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4440 if (arg0_value == ag->codegen->invalid_inst_src)
4441 return arg0_value;
4442
4443 Stage1ZirInst *fence = ir_build_fence(ag, scope, node, arg0_value);
4444 return ir_lval_wrap(ag, scope, fence, lval, result_loc);
4445 }
4446 case BuiltinFnIdReduce:
4447 {
4448 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4449 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4450 if (arg0_value == ag->codegen->invalid_inst_src)
4451 return arg0_value;
4452
4453 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4454 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4455 if (arg1_value == ag->codegen->invalid_inst_src)
4456 return arg1_value;
4457
4458 Stage1ZirInst *reduce = ir_build_reduce(ag, scope, node, arg0_value, arg1_value);
4459 return ir_lval_wrap(ag, scope, reduce, lval, result_loc);
4460 }
4461 case BuiltinFnIdDivExact:
4462 {
4463 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4464 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4465 if (arg0_value == ag->codegen->invalid_inst_src)
4466 return arg0_value;
4467
4468 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4469 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4470 if (arg1_value == ag->codegen->invalid_inst_src)
4471 return arg1_value;
4472
4473 Stage1ZirInst *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpDivExact, arg0_value, arg1_value, true);
4474 return ir_lval_wrap(ag, scope, bin_op, lval, result_loc);
4475 }
4476 case BuiltinFnIdDivTrunc:
4477 {
4478 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4479 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4480 if (arg0_value == ag->codegen->invalid_inst_src)
4481 return arg0_value;
4482
4483 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4484 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4485 if (arg1_value == ag->codegen->invalid_inst_src)
4486 return arg1_value;
4487
4488 Stage1ZirInst *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpDivTrunc, arg0_value, arg1_value, true);
4489 return ir_lval_wrap(ag, scope, bin_op, lval, result_loc);
4490 }
4491 case BuiltinFnIdDivFloor:
4492 {
4493 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4494 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4495 if (arg0_value == ag->codegen->invalid_inst_src)
4496 return arg0_value;
4497
4498 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4499 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4500 if (arg1_value == ag->codegen->invalid_inst_src)
4501 return arg1_value;
4502
4503 Stage1ZirInst *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpDivFloor, arg0_value, arg1_value, true);
4504 return ir_lval_wrap(ag, scope, bin_op, lval, result_loc);
4505 }
4506 case BuiltinFnIdRem:
4507 {
4508 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4509 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4510 if (arg0_value == ag->codegen->invalid_inst_src)
4511 return arg0_value;
4512
4513 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4514 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4515 if (arg1_value == ag->codegen->invalid_inst_src)
4516 return arg1_value;
4517
4518 Stage1ZirInst *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpRemRem, arg0_value, arg1_value, true);
4519 return ir_lval_wrap(ag, scope, bin_op, lval, result_loc);
4520 }
4521 case BuiltinFnIdMod:
4522 {
4523 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4524 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4525 if (arg0_value == ag->codegen->invalid_inst_src)
4526 return arg0_value;
4527
4528 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4529 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4530 if (arg1_value == ag->codegen->invalid_inst_src)
4531 return arg1_value;
4532
4533 Stage1ZirInst *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpRemMod, arg0_value, arg1_value, true);
4534 return ir_lval_wrap(ag, scope, bin_op, lval, result_loc);
4535 }
4536 case BuiltinFnIdSqrt:
4537 case BuiltinFnIdSin:
4538 case BuiltinFnIdCos:
4539 case BuiltinFnIdTan:
4540 case BuiltinFnIdExp:
4541 case BuiltinFnIdExp2:
4542 case BuiltinFnIdLog:
4543 case BuiltinFnIdLog2:
4544 case BuiltinFnIdLog10:
4545 case BuiltinFnIdFabs:
4546 case BuiltinFnIdFloor:
4547 case BuiltinFnIdCeil:
4548 case BuiltinFnIdTrunc:
4549 case BuiltinFnIdNearbyInt:
4550 case BuiltinFnIdRound:
4551 {
4552 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4553 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4554 if (arg0_value == ag->codegen->invalid_inst_src)
4555 return arg0_value;
4556
4557 Stage1ZirInst *inst = ir_build_float_op_src(ag, scope, node, arg0_value, builtin_fn->id);
4558 return ir_lval_wrap(ag, scope, inst, lval, result_loc);
4559 }
4560 case BuiltinFnIdTruncate:
4561 {
4562 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4563 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4564 if (arg0_value == ag->codegen->invalid_inst_src)
4565 return arg0_value;
4566
4567 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4568 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4569 if (arg1_value == ag->codegen->invalid_inst_src)
4570 return arg1_value;
4571
4572 Stage1ZirInst *truncate = ir_build_truncate(ag, scope, node, arg0_value, arg1_value);
4573 return ir_lval_wrap(ag, scope, truncate, lval, result_loc);
4574 }
4575 case BuiltinFnIdIntCast:
4576 {
4577 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4578 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4579 if (arg0_value == ag->codegen->invalid_inst_src)
4580 return arg0_value;
4581
4582 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4583 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4584 if (arg1_value == ag->codegen->invalid_inst_src)
4585 return arg1_value;
4586
4587 Stage1ZirInst *result = ir_build_int_cast(ag, scope, node, arg0_value, arg1_value);
4588 return ir_lval_wrap(ag, scope, result, lval, result_loc);
4589 }
4590 case BuiltinFnIdFloatCast:
4591 {
4592 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4593 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4594 if (arg0_value == ag->codegen->invalid_inst_src)
4595 return arg0_value;
4596
4597 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4598 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4599 if (arg1_value == ag->codegen->invalid_inst_src)
4600 return arg1_value;
4601
4602 Stage1ZirInst *result = ir_build_float_cast(ag, scope, node, arg0_value, arg1_value);
4603 return ir_lval_wrap(ag, scope, result, lval, result_loc);
4604 }
4605 case BuiltinFnIdErrSetCast:
4606 {
4607 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4608 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4609 if (arg0_value == ag->codegen->invalid_inst_src)
4610 return arg0_value;
4611
4612 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4613 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4614 if (arg1_value == ag->codegen->invalid_inst_src)
4615 return arg1_value;
4616
4617 Stage1ZirInst *result = ir_build_err_set_cast(ag, scope, node, arg0_value, arg1_value);
4618 return ir_lval_wrap(ag, scope, result, lval, result_loc);
4619 }
4620 case BuiltinFnIdIntToFloat:
4621 {
4622 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4623 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4624 if (arg0_value == ag->codegen->invalid_inst_src)
4625 return arg0_value;
4626
4627 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4628 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4629 if (arg1_value == ag->codegen->invalid_inst_src)
4630 return arg1_value;
4631
4632 Stage1ZirInst *result = ir_build_int_to_float(ag, scope, node, arg0_value, arg1_value);
4633 return ir_lval_wrap(ag, scope, result, lval, result_loc);
4634 }
4635 case BuiltinFnIdFloatToInt:
4636 {
4637 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4638 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4639 if (arg0_value == ag->codegen->invalid_inst_src)
4640 return arg0_value;
4641
4642 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4643 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4644 if (arg1_value == ag->codegen->invalid_inst_src)
4645 return arg1_value;
4646
4647 Stage1ZirInst *result = ir_build_float_to_int(ag, scope, node, arg0_value, arg1_value);
4648 return ir_lval_wrap(ag, scope, result, lval, result_loc);
4649 }
4650 case BuiltinFnIdErrToInt:
4651 {
4652 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4653 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4654 if (arg0_value == ag->codegen->invalid_inst_src)
4655 return arg0_value;
4656
4657 Stage1ZirInst *result = ir_build_err_to_int_src(ag, scope, node, arg0_value);
4658 return ir_lval_wrap(ag, scope, result, lval, result_loc);
4659 }
4660 case BuiltinFnIdIntToErr:
4661 {
4662 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4663 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4664 if (arg0_value == ag->codegen->invalid_inst_src)
4665 return arg0_value;
4666
4667 Stage1ZirInst *result = ir_build_int_to_err_src(ag, scope, node, arg0_value);
4668 return ir_lval_wrap(ag, scope, result, lval, result_loc);
4669 }
4670 case BuiltinFnIdBoolToInt:
4671 {
4672 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4673 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4674 if (arg0_value == ag->codegen->invalid_inst_src)
4675 return arg0_value;
4676
4677 Stage1ZirInst *result = ir_build_bool_to_int(ag, scope, node, arg0_value);
4678 return ir_lval_wrap(ag, scope, result, lval, result_loc);
4679 }
4680 case BuiltinFnIdVectorType:
4681 {
4682 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4683 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4684 if (arg0_value == ag->codegen->invalid_inst_src)
4685 return arg0_value;
4686
4687 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4688 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4689 if (arg1_value == ag->codegen->invalid_inst_src)
4690 return arg1_value;
4691
4692 Stage1ZirInst *vector_type = ir_build_vector_type(ag, scope, node, arg0_value, arg1_value);
4693 return ir_lval_wrap(ag, scope, vector_type, lval, result_loc);
4694 }
4695 case BuiltinFnIdShuffle:
4696 {
4697 // Used for the type expr and the mask expr
4698 Scope *comptime_scope = create_comptime_scope(ag->codegen, node, scope);
4699
4700 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4701 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, comptime_scope);
4702 if (arg0_value == ag->codegen->invalid_inst_src)
4703 return arg0_value;
4704
4705 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4706 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4707 if (arg1_value == ag->codegen->invalid_inst_src)
4708 return arg1_value;
4709
4710 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
4711 Stage1ZirInst *arg2_value = astgen_node(ag, arg2_node, scope);
4712 if (arg2_value == ag->codegen->invalid_inst_src)
4713 return arg2_value;
4714
4715 AstNode *arg3_node = node->data.fn_call_expr.params.at(3);
4716 Stage1ZirInst *arg3_value = astgen_node(ag, arg3_node, comptime_scope);
4717 if (arg3_value == ag->codegen->invalid_inst_src)
4718 return arg3_value;
4719
4720 Stage1ZirInst *shuffle_vector = ir_build_shuffle_vector(ag, scope, node,
4721 arg0_value, arg1_value, arg2_value, arg3_value);
4722 return ir_lval_wrap(ag, scope, shuffle_vector, lval, result_loc);
4723 }
4724 case BuiltinFnIdSelect:
4725 {
4726 // Used for the type expr
4727 Scope *comptime_scope = create_comptime_scope(ag->codegen, node, scope);
4728
4729 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4730 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, comptime_scope);
4731 if (arg0_value == ag->codegen->invalid_inst_src)
4732 return arg0_value;
4733
4734 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4735 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4736 if (arg1_value == ag->codegen->invalid_inst_src)
4737 return arg1_value;
4738
4739 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
4740 Stage1ZirInst *arg2_value = astgen_node(ag, arg2_node, scope);
4741 if (arg2_value == ag->codegen->invalid_inst_src)
4742 return arg2_value;
4743
4744 AstNode *arg3_node = node->data.fn_call_expr.params.at(3);
4745 Stage1ZirInst *arg3_value = astgen_node(ag, arg3_node, scope);
4746 if (arg3_value == ag->codegen->invalid_inst_src)
4747 return arg3_value;
4748
4749 Stage1ZirInst *select = ir_build_select(ag, scope, node,
4750 arg0_value, arg1_value, arg2_value, arg3_value);
4751 return ir_lval_wrap(ag, scope, select, lval, result_loc);
4752 }
4753 case BuiltinFnIdSplat:
4754 {
4755 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4756 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4757 if (arg0_value == ag->codegen->invalid_inst_src)
4758 return arg0_value;
4759
4760 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4761 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4762 if (arg1_value == ag->codegen->invalid_inst_src)
4763 return arg1_value;
4764
4765 Stage1ZirInst *splat = ir_build_splat_src(ag, scope, node,
4766 arg0_value, arg1_value);
4767 return ir_lval_wrap(ag, scope, splat, lval, result_loc);
4768 }
4769 case BuiltinFnIdMaximum:
4770 {
4771 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4772 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4773 if (arg0_value == ag->codegen->invalid_inst_src)
4774 return arg0_value;
4775
4776 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4777 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4778 if (arg1_value == ag->codegen->invalid_inst_src)
4779 return arg1_value;
4780
4781 Stage1ZirInst *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpMax, arg0_value, arg1_value, true);
4782 return ir_lval_wrap(ag, scope, bin_op, lval, result_loc);
4783 }
4784 case BuiltinFnIdMemcpy:
4785 {
4786 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4787 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4788 if (arg0_value == ag->codegen->invalid_inst_src)
4789 return arg0_value;
4790
4791 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4792 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4793 if (arg1_value == ag->codegen->invalid_inst_src)
4794 return arg1_value;
4795
4796 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
4797 Stage1ZirInst *arg2_value = astgen_node(ag, arg2_node, scope);
4798 if (arg2_value == ag->codegen->invalid_inst_src)
4799 return arg2_value;
4800
4801 Stage1ZirInst *ir_memcpy = ir_build_memcpy_src(ag, scope, node, arg0_value, arg1_value, arg2_value);
4802 return ir_lval_wrap(ag, scope, ir_memcpy, lval, result_loc);
4803 }
4804 case BuiltinFnIdMemset:
4805 {
4806 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4807 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4808 if (arg0_value == ag->codegen->invalid_inst_src)
4809 return arg0_value;
4810
4811 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4812 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4813 if (arg1_value == ag->codegen->invalid_inst_src)
4814 return arg1_value;
4815
4816 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
4817 Stage1ZirInst *arg2_value = astgen_node(ag, arg2_node, scope);
4818 if (arg2_value == ag->codegen->invalid_inst_src)
4819 return arg2_value;
4820
4821 Stage1ZirInst *ir_memset = ir_build_memset_src(ag, scope, node, arg0_value, arg1_value, arg2_value);
4822 return ir_lval_wrap(ag, scope, ir_memset, lval, result_loc);
4823 }
4824 case BuiltinFnIdMinimum:
4825 {
4826 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4827 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4828 if (arg0_value == ag->codegen->invalid_inst_src)
4829 return arg0_value;
4830
4831 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4832 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4833 if (arg1_value == ag->codegen->invalid_inst_src)
4834 return arg1_value;
4835
4836 Stage1ZirInst *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpMin, arg0_value, arg1_value, true);
4837 return ir_lval_wrap(ag, scope, bin_op, lval, result_loc);
4838 }
4839 case BuiltinFnIdWasmMemorySize:
4840 {
4841 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4842 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4843 if (arg0_value == ag->codegen->invalid_inst_src)
4844 return arg0_value;
4845
4846 Stage1ZirInst *ir_wasm_memory_size = ir_build_wasm_memory_size_src(ag, scope, node, arg0_value);
4847 return ir_lval_wrap(ag, scope, ir_wasm_memory_size, lval, result_loc);
4848 }
4849 case BuiltinFnIdWasmMemoryGrow:
4850 {
4851 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4852 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4853 if (arg0_value == ag->codegen->invalid_inst_src)
4854 return arg0_value;
4855
4856 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4857 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4858 if (arg1_value == ag->codegen->invalid_inst_src)
4859 return arg1_value;
4860
4861 Stage1ZirInst *ir_wasm_memory_grow = ir_build_wasm_memory_grow_src(ag, scope, node, arg0_value, arg1_value);
4862 return ir_lval_wrap(ag, scope, ir_wasm_memory_grow, lval, result_loc);
4863 }
4864 case BuiltinFnIdField:
4865 {
4866 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4867 Stage1ZirInst *arg0_value = astgen_node_extra(ag, arg0_node, scope, LValPtr, nullptr);
4868 if (arg0_value == ag->codegen->invalid_inst_src)
4869 return arg0_value;
4870
4871 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4872 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4873 if (arg1_value == ag->codegen->invalid_inst_src)
4874 return arg1_value;
4875
4876 Stage1ZirInst *ptr_instruction = ir_build_field_ptr_instruction(ag, scope, node,
4877 arg0_value, arg1_value, false);
4878
4879 if (lval == LValPtr || lval == LValAssign)
4880 return ptr_instruction;
4881
4882 Stage1ZirInst *load_ptr = ir_build_load_ptr(ag, scope, node, ptr_instruction);
4883 return ir_expr_wrap(ag, scope, load_ptr, result_loc);
4884 }
4885 case BuiltinFnIdHasField:
4886 {
4887 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4888 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4889 if (arg0_value == ag->codegen->invalid_inst_src)
4890 return arg0_value;
4891
4892 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4893 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4894 if (arg1_value == ag->codegen->invalid_inst_src)
4895 return arg1_value;
4896
4897 Stage1ZirInst *type_info = ir_build_has_field(ag, scope, node, arg0_value, arg1_value);
4898 return ir_lval_wrap(ag, scope, type_info, lval, result_loc);
4899 }
4900 case BuiltinFnIdTypeInfo:
4901 {
4902 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4903 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4904 if (arg0_value == ag->codegen->invalid_inst_src)
4905 return arg0_value;
4906
4907 Stage1ZirInst *type_info = ir_build_type_info(ag, scope, node, arg0_value);
4908 return ir_lval_wrap(ag, scope, type_info, lval, result_loc);
4909 }
4910 case BuiltinFnIdType:
4911 {
4912 AstNode *arg_node = node->data.fn_call_expr.params.at(0);
4913 Stage1ZirInst *arg = astgen_node(ag, arg_node, scope);
4914 if (arg == ag->codegen->invalid_inst_src)
4915 return arg;
4916
4917 Stage1ZirInst *type = ir_build_type(ag, scope, node, arg);
4918 return ir_lval_wrap(ag, scope, type, lval, result_loc);
4919 }
4920 case BuiltinFnIdBreakpoint:
4921 return ir_lval_wrap(ag, scope, ir_build_breakpoint(ag, scope, node), lval, result_loc);
4922 case BuiltinFnIdReturnAddress:
4923 return ir_lval_wrap(ag, scope, ir_build_return_address_src(ag, scope, node), lval, result_loc);
4924 case BuiltinFnIdFrameAddress:
4925 return ir_lval_wrap(ag, scope, ir_build_frame_address_src(ag, scope, node), lval, result_loc);
4926 case BuiltinFnIdFrameHandle:
4927 if (ag->fn == nullptr) {
4928 add_node_error(ag->codegen, node,
4929 buf_sprintf("@frame() called outside of function definition"));
4930 return ag->codegen->invalid_inst_src;
4931 }
4932 return ir_lval_wrap(ag, scope, ir_build_handle_src(ag, scope, node), lval, result_loc);
4933 case BuiltinFnIdFrameType: {
4934 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4935 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4936 if (arg0_value == ag->codegen->invalid_inst_src)
4937 return arg0_value;
4938
4939 Stage1ZirInst *frame_type = ir_build_frame_type(ag, scope, node, arg0_value);
4940 return ir_lval_wrap(ag, scope, frame_type, lval, result_loc);
4941 }
4942 case BuiltinFnIdFrameSize: {
4943 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4944 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4945 if (arg0_value == ag->codegen->invalid_inst_src)
4946 return arg0_value;
4947
4948 Stage1ZirInst *frame_size = ir_build_frame_size_src(ag, scope, node, arg0_value);
4949 return ir_lval_wrap(ag, scope, frame_size, lval, result_loc);
4950 }
4951 case BuiltinFnIdAlignOf:
4952 {
4953 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4954 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4955 if (arg0_value == ag->codegen->invalid_inst_src)
4956 return arg0_value;
4957
4958 Stage1ZirInst *align_of = ir_build_align_of(ag, scope, node, arg0_value);
4959 return ir_lval_wrap(ag, scope, align_of, lval, result_loc);
4960 }
4961 case BuiltinFnIdAddWithOverflow:
4962 return ir_lval_wrap(ag, scope, astgen_overflow_op(ag, scope, node, IrOverflowOpAdd), lval, result_loc);
4963 case BuiltinFnIdSubWithOverflow:
4964 return ir_lval_wrap(ag, scope, astgen_overflow_op(ag, scope, node, IrOverflowOpSub), lval, result_loc);
4965 case BuiltinFnIdMulWithOverflow:
4966 return ir_lval_wrap(ag, scope, astgen_overflow_op(ag, scope, node, IrOverflowOpMul), lval, result_loc);
4967 case BuiltinFnIdShlWithOverflow:
4968 return ir_lval_wrap(ag, scope, astgen_overflow_op(ag, scope, node, IrOverflowOpShl), lval, result_loc);
4969 case BuiltinFnIdMulAdd:
4970 return ir_lval_wrap(ag, scope, astgen_mul_add(ag, scope, node), lval, result_loc);
4971 case BuiltinFnIdTypeName:
4972 {
4973 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4974 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4975 if (arg0_value == ag->codegen->invalid_inst_src)
4976 return arg0_value;
4977
4978 Stage1ZirInst *type_name = ir_build_type_name(ag, scope, node, arg0_value);
4979 return ir_lval_wrap(ag, scope, type_name, lval, result_loc);
4980 }
4981 case BuiltinFnIdPanic:
4982 {
4983 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4984 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4985 if (arg0_value == ag->codegen->invalid_inst_src)
4986 return arg0_value;
4987
4988 Stage1ZirInst *panic = ir_build_panic_src(ag, scope, node, arg0_value);
4989 return ir_lval_wrap(ag, scope, panic, lval, result_loc);
4990 }
4991 case BuiltinFnIdPtrCast:
4992 {
4993 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4994 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
4995 if (arg0_value == ag->codegen->invalid_inst_src)
4996 return arg0_value;
4997
4998 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4999 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5000 if (arg1_value == ag->codegen->invalid_inst_src)
5001 return arg1_value;
5002
5003 Stage1ZirInst *ptr_cast = ir_build_ptr_cast_src(ag, scope, node, arg0_value, arg1_value, true);
5004 return ir_lval_wrap(ag, scope, ptr_cast, lval, result_loc);
5005 }
5006 case BuiltinFnIdBitCast:
5007 {
5008 AstNode *dest_type_node = node->data.fn_call_expr.params.at(0);
5009 Stage1ZirInst *dest_type = astgen_node(ag, dest_type_node, scope);
5010 if (dest_type == ag->codegen->invalid_inst_src)
5011 return dest_type;
5012
5013 ResultLocBitCast *result_loc_bit_cast = heap::c_allocator.create<ResultLocBitCast>();
5014 result_loc_bit_cast->base.id = ResultLocIdBitCast;
5015 result_loc_bit_cast->base.source_instruction = dest_type;
5016 result_loc_bit_cast->base.allow_write_through_const = result_loc->allow_write_through_const;
5017 ir_ref_instruction(dest_type, ag->current_basic_block);
5018 result_loc_bit_cast->parent = result_loc;
5019
5020 ir_build_reset_result(ag, scope, node, &result_loc_bit_cast->base);
5021
5022 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5023 Stage1ZirInst *arg1_value = astgen_node_extra(ag, arg1_node, scope, LValNone,
5024 &result_loc_bit_cast->base);
5025 if (arg1_value == ag->codegen->invalid_inst_src)
5026 return arg1_value;
5027
5028 Stage1ZirInst *bitcast = ir_build_bit_cast_src(ag, scope, arg1_node, arg1_value, result_loc_bit_cast);
5029 return ir_lval_wrap(ag, scope, bitcast, lval, result_loc);
5030 }
5031 case BuiltinFnIdAs:
5032 {
5033 AstNode *dest_type_node = node->data.fn_call_expr.params.at(0);
5034 Stage1ZirInst *dest_type = astgen_node(ag, dest_type_node, scope);
5035 if (dest_type == ag->codegen->invalid_inst_src)
5036 return dest_type;
5037
5038 ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, dest_type, result_loc);
5039
5040 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5041 Stage1ZirInst *arg1_value = astgen_node_extra(ag, arg1_node, scope, LValNone,
5042 &result_loc_cast->base);
5043 if (arg1_value == ag->codegen->invalid_inst_src)
5044 return arg1_value;
5045
5046 Stage1ZirInst *result = ir_build_implicit_cast(ag, scope, node, arg1_value, result_loc_cast);
5047 return ir_lval_wrap(ag, scope, result, lval, result_loc);
5048 }
5049 case BuiltinFnIdIntToPtr:
5050 {
5051 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5052 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5053 if (arg0_value == ag->codegen->invalid_inst_src)
5054 return arg0_value;
5055
5056 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5057 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5058 if (arg1_value == ag->codegen->invalid_inst_src)
5059 return arg1_value;
5060
5061 Stage1ZirInst *int_to_ptr = ir_build_int_to_ptr_src(ag, scope, node, arg0_value, arg1_value);
5062 return ir_lval_wrap(ag, scope, int_to_ptr, lval, result_loc);
5063 }
5064 case BuiltinFnIdPtrToInt:
5065 {
5066 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5067 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5068 if (arg0_value == ag->codegen->invalid_inst_src)
5069 return arg0_value;
5070
5071 Stage1ZirInst *ptr_to_int = ir_build_ptr_to_int_src(ag, scope, node, arg0_value);
5072 return ir_lval_wrap(ag, scope, ptr_to_int, lval, result_loc);
5073 }
5074 case BuiltinFnIdTagName:
5075 {
5076 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5077 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5078 if (arg0_value == ag->codegen->invalid_inst_src)
5079 return arg0_value;
5080
5081 Stage1ZirInst *tag_name = ir_build_tag_name_src(ag, scope, node, arg0_value);
5082 return ir_lval_wrap(ag, scope, tag_name, lval, result_loc);
5083 }
5084 case BuiltinFnIdFieldParentPtr:
5085 {
5086 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5087 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5088 if (arg0_value == ag->codegen->invalid_inst_src)
5089 return arg0_value;
5090
5091 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5092 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5093 if (arg1_value == ag->codegen->invalid_inst_src)
5094 return arg1_value;
5095
5096 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
5097 Stage1ZirInst *arg2_value = astgen_node(ag, arg2_node, scope);
5098 if (arg2_value == ag->codegen->invalid_inst_src)
5099 return arg2_value;
5100
5101 Stage1ZirInst *field_parent_ptr = ir_build_field_parent_ptr_src(ag, scope, node,
5102 arg0_value, arg1_value, arg2_value);
5103 return ir_lval_wrap(ag, scope, field_parent_ptr, lval, result_loc);
5104 }
5105 case BuiltinFnIdOffsetOf:
5106 {
5107 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5108 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5109 if (arg0_value == ag->codegen->invalid_inst_src)
5110 return arg0_value;
5111
5112 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5113 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5114 if (arg1_value == ag->codegen->invalid_inst_src)
5115 return arg1_value;
5116
5117 Stage1ZirInst *offset_of = ir_build_offset_of(ag, scope, node, arg0_value, arg1_value);
5118 return ir_lval_wrap(ag, scope, offset_of, lval, result_loc);
5119 }
5120 case BuiltinFnIdBitOffsetOf:
5121 {
5122 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5123 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5124 if (arg0_value == ag->codegen->invalid_inst_src)
5125 return arg0_value;
5126
5127 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5128 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5129 if (arg1_value == ag->codegen->invalid_inst_src)
5130 return arg1_value;
5131
5132 Stage1ZirInst *offset_of = ir_build_bit_offset_of(ag, scope, node, arg0_value, arg1_value);
5133 return ir_lval_wrap(ag, scope, offset_of, lval, result_loc);
5134 }
5135 case BuiltinFnIdCall: {
5136 // Cast the options parameter to the options type
5137 ZigType *options_type = get_builtin_type(ag->codegen, "CallOptions");
5138 Stage1ZirInst *options_type_inst = ir_build_const_type(ag, scope, node, options_type);
5139 ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc());
5140
5141 AstNode *options_node = node->data.fn_call_expr.params.at(0);
5142 Stage1ZirInst *options_inner = astgen_node_extra(ag, options_node, scope,
5143 LValNone, &result_loc_cast->base);
5144 if (options_inner == ag->codegen->invalid_inst_src)
5145 return options_inner;
5146 Stage1ZirInst *options = ir_build_implicit_cast(ag, scope, options_node, options_inner, result_loc_cast);
5147
5148 AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1);
5149 AstNode *args_node = node->data.fn_call_expr.params.at(2);
5150 if (args_node->type == NodeTypeContainerInitExpr) {
5151 if (args_node->data.container_init_expr.kind == ContainerInitKindArray ||
5152 args_node->data.container_init_expr.entries.length == 0)
5153 {
5154 return astgen_fn_call_with_args(ag, scope, node,
5155 fn_ref_node, CallModifierNone, options,
5156 args_node->data.container_init_expr.entries.items,
5157 args_node->data.container_init_expr.entries.length,
5158 lval, result_loc);
5159 } else {
5160 exec_add_error_node(ag->codegen, ag->exec, args_node,
5161 buf_sprintf("TODO: @call with anon struct literal"));
5162 return ag->codegen->invalid_inst_src;
5163 }
5164 } else {
5165 Stage1ZirInst *fn_ref = astgen_node(ag, fn_ref_node, scope);
5166 if (fn_ref == ag->codegen->invalid_inst_src)
5167 return fn_ref;
5168
5169 Stage1ZirInst *args = astgen_node(ag, args_node, scope);
5170 if (args == ag->codegen->invalid_inst_src)
5171 return args;
5172
5173 Stage1ZirInst *call = ir_build_call_extra(ag, scope, node, options, fn_ref, args, result_loc);
5174 return ir_lval_wrap(ag, scope, call, lval, result_loc);
5175 }
5176 }
5177 case BuiltinFnIdAsyncCall:
5178 return astgen_async_call(ag, scope, nullptr, node, lval, result_loc);
5179 case BuiltinFnIdShlExact:
5180 {
5181 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5182 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5183 if (arg0_value == ag->codegen->invalid_inst_src)
5184 return arg0_value;
5185
5186 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5187 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5188 if (arg1_value == ag->codegen->invalid_inst_src)
5189 return arg1_value;
5190
5191 Stage1ZirInst *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpBitShiftLeftExact, arg0_value, arg1_value, true);
5192 return ir_lval_wrap(ag, scope, bin_op, lval, result_loc);
5193 }
5194 case BuiltinFnIdShrExact:
5195 {
5196 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5197 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5198 if (arg0_value == ag->codegen->invalid_inst_src)
5199 return arg0_value;
5200
5201 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5202 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5203 if (arg1_value == ag->codegen->invalid_inst_src)
5204 return arg1_value;
5205
5206 Stage1ZirInst *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true);
5207 return ir_lval_wrap(ag, scope, bin_op, lval, result_loc);
5208 }
5209 case BuiltinFnIdSetEvalBranchQuota:
5210 {
5211 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5212 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5213 if (arg0_value == ag->codegen->invalid_inst_src)
5214 return arg0_value;
5215
5216 Stage1ZirInst *set_eval_branch_quota = ir_build_set_eval_branch_quota(ag, scope, node, arg0_value);
5217 return ir_lval_wrap(ag, scope, set_eval_branch_quota, lval, result_loc);
5218 }
5219 case BuiltinFnIdAlignCast:
5220 {
5221 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5222 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5223 if (arg0_value == ag->codegen->invalid_inst_src)
5224 return arg0_value;
5225
5226 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5227 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5228 if (arg1_value == ag->codegen->invalid_inst_src)
5229 return arg1_value;
5230
5231 Stage1ZirInst *align_cast = ir_build_align_cast_src(ag, scope, node, arg0_value, arg1_value);
5232 return ir_lval_wrap(ag, scope, align_cast, lval, result_loc);
5233 }
5234 case BuiltinFnIdThis:
5235 {
5236 Stage1ZirInst *this_inst = astgen_this(ag, scope, node);
5237 return ir_lval_wrap(ag, scope, this_inst, lval, result_loc);
5238 }
5239 case BuiltinFnIdSetAlignStack:
5240 {
5241 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5242 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5243 if (arg0_value == ag->codegen->invalid_inst_src)
5244 return arg0_value;
5245
5246 Stage1ZirInst *set_align_stack = ir_build_set_align_stack(ag, scope, node, arg0_value);
5247 return ir_lval_wrap(ag, scope, set_align_stack, lval, result_loc);
5248 }
5249 case BuiltinFnIdExport:
5250 {
5251 // Cast the options parameter to the options type
5252 ZigType *options_type = get_builtin_type(ag->codegen, "ExportOptions");
5253 Stage1ZirInst *options_type_inst = ir_build_const_type(ag, scope, node, options_type);
5254 ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc());
5255
5256 AstNode *target_node = node->data.fn_call_expr.params.at(0);
5257 Stage1ZirInst *target_value = astgen_node(ag, target_node, scope);
5258 if (target_value == ag->codegen->invalid_inst_src)
5259 return target_value;
5260
5261 AstNode *options_node = node->data.fn_call_expr.params.at(1);
5262 Stage1ZirInst *options_value = astgen_node_extra(ag, options_node,
5263 scope, LValNone, &result_loc_cast->base);
5264 if (options_value == ag->codegen->invalid_inst_src)
5265 return options_value;
5266
5267 Stage1ZirInst *casted_options_value = ir_build_implicit_cast(
5268 ag, scope, options_node, options_value, result_loc_cast);
5269
5270 Stage1ZirInst *ir_export = ir_build_export(ag, scope, node, target_value, casted_options_value);
5271 return ir_lval_wrap(ag, scope, ir_export, lval, result_loc);
5272 }
5273 case BuiltinFnIdExtern:
5274 {
5275 // Cast the options parameter to the options type
5276 ZigType *options_type = get_builtin_type(ag->codegen, "ExternOptions");
5277 Stage1ZirInst *options_type_inst = ir_build_const_type(ag, scope, node, options_type);
5278 ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc());
5279
5280 AstNode *type_node = node->data.fn_call_expr.params.at(0);
5281 Stage1ZirInst *type_value = astgen_node(ag, type_node, scope);
5282 if (type_value == ag->codegen->invalid_inst_src)
5283 return type_value;
5284
5285 AstNode *options_node = node->data.fn_call_expr.params.at(1);
5286 Stage1ZirInst *options_value = astgen_node_extra(ag, options_node,
5287 scope, LValNone, &result_loc_cast->base);
5288 if (options_value == ag->codegen->invalid_inst_src)
5289 return options_value;
5290
5291 Stage1ZirInst *casted_options_value = ir_build_implicit_cast(
5292 ag, scope, options_node, options_value, result_loc_cast);
5293
5294 Stage1ZirInst *ir_extern = ir_build_extern(ag, scope, node, type_value, casted_options_value);
5295 return ir_lval_wrap(ag, scope, ir_extern, lval, result_loc);
5296 }
5297 case BuiltinFnIdErrorReturnTrace:
5298 {
5299 Stage1ZirInst *error_return_trace = ir_build_error_return_trace_src(ag, scope, node,
5300 IrInstErrorReturnTraceNull);
5301 return ir_lval_wrap(ag, scope, error_return_trace, lval, result_loc);
5302 }
5303 case BuiltinFnIdAtomicRmw:
5304 {
5305 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5306 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5307 if (arg0_value == ag->codegen->invalid_inst_src)
5308 return arg0_value;
5309
5310 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5311 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5312 if (arg1_value == ag->codegen->invalid_inst_src)
5313 return arg1_value;
5314
5315 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
5316 Stage1ZirInst *arg2_value = astgen_node(ag, arg2_node, scope);
5317 if (arg2_value == ag->codegen->invalid_inst_src)
5318 return arg2_value;
5319
5320 AstNode *arg3_node = node->data.fn_call_expr.params.at(3);
5321 Stage1ZirInst *arg3_value = astgen_node(ag, arg3_node, scope);
5322 if (arg3_value == ag->codegen->invalid_inst_src)
5323 return arg3_value;
5324
5325 AstNode *arg4_node = node->data.fn_call_expr.params.at(4);
5326 Stage1ZirInst *arg4_value = astgen_node(ag, arg4_node, scope);
5327 if (arg4_value == ag->codegen->invalid_inst_src)
5328 return arg4_value;
5329
5330 Stage1ZirInst *inst = ir_build_atomic_rmw_src(ag, scope, node,
5331 arg0_value, arg1_value, arg2_value, arg3_value, arg4_value);
5332 return ir_lval_wrap(ag, scope, inst, lval, result_loc);
5333 }
5334 case BuiltinFnIdAtomicLoad:
5335 {
5336 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5337 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5338 if (arg0_value == ag->codegen->invalid_inst_src)
5339 return arg0_value;
5340
5341 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5342 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5343 if (arg1_value == ag->codegen->invalid_inst_src)
5344 return arg1_value;
5345
5346 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
5347 Stage1ZirInst *arg2_value = astgen_node(ag, arg2_node, scope);
5348 if (arg2_value == ag->codegen->invalid_inst_src)
5349 return arg2_value;
5350
5351 Stage1ZirInst *inst = ir_build_atomic_load_src(ag, scope, node, arg0_value, arg1_value, arg2_value);
5352 return ir_lval_wrap(ag, scope, inst, lval, result_loc);
5353 }
5354 case BuiltinFnIdAtomicStore:
5355 {
5356 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5357 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5358 if (arg0_value == ag->codegen->invalid_inst_src)
5359 return arg0_value;
5360
5361 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5362 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5363 if (arg1_value == ag->codegen->invalid_inst_src)
5364 return arg1_value;
5365
5366 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
5367 Stage1ZirInst *arg2_value = astgen_node(ag, arg2_node, scope);
5368 if (arg2_value == ag->codegen->invalid_inst_src)
5369 return arg2_value;
5370
5371 AstNode *arg3_node = node->data.fn_call_expr.params.at(3);
5372 Stage1ZirInst *arg3_value = astgen_node(ag, arg3_node, scope);
5373 if (arg3_value == ag->codegen->invalid_inst_src)
5374 return arg3_value;
5375
5376 Stage1ZirInst *inst = ir_build_atomic_store_src(ag, scope, node, arg0_value, arg1_value,
5377 arg2_value, arg3_value);
5378 return ir_lval_wrap(ag, scope, inst, lval, result_loc);
5379 }
5380 case BuiltinFnIdIntToEnum:
5381 {
5382 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5383 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5384 if (arg0_value == ag->codegen->invalid_inst_src)
5385 return arg0_value;
5386
5387 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5388 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5389 if (arg1_value == ag->codegen->invalid_inst_src)
5390 return arg1_value;
5391
5392 Stage1ZirInst *result = ir_build_int_to_enum_src(ag, scope, node, arg0_value, arg1_value);
5393 return ir_lval_wrap(ag, scope, result, lval, result_loc);
5394 }
5395 case BuiltinFnIdEnumToInt:
5396 {
5397 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5398 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5399 if (arg0_value == ag->codegen->invalid_inst_src)
5400 return arg0_value;
5401
5402 Stage1ZirInst *result = ir_build_enum_to_int(ag, scope, node, arg0_value);
5403 return ir_lval_wrap(ag, scope, result, lval, result_loc);
5404 }
5405 case BuiltinFnIdCtz:
5406 case BuiltinFnIdPopCount:
5407 case BuiltinFnIdClz:
5408 case BuiltinFnIdBswap:
5409 case BuiltinFnIdBitReverse:
5410 {
5411 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5412 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5413 if (arg0_value == ag->codegen->invalid_inst_src)
5414 return arg0_value;
5415
5416 Stage1ZirInst *arg1_value = arg0_value;
5417 arg0_value = ir_build_typeof_1(ag, scope, arg0_node, arg1_value);
5418
5419 Stage1ZirInst *result;
5420 switch (builtin_fn->id) {
5421 case BuiltinFnIdCtz:
5422 result = ir_build_ctz(ag, scope, node, arg0_value, arg1_value);
5423 break;
5424 case BuiltinFnIdPopCount:
5425 result = ir_build_pop_count(ag, scope, node, arg0_value, arg1_value);
5426 break;
5427 case BuiltinFnIdClz:
5428 result = ir_build_clz(ag, scope, node, arg0_value, arg1_value);
5429 break;
5430 case BuiltinFnIdBswap:
5431 result = ir_build_bswap(ag, scope, node, arg0_value, arg1_value);
5432 break;
5433 case BuiltinFnIdBitReverse:
5434 result = ir_build_bit_reverse(ag, scope, node, arg0_value, arg1_value);
5435 break;
5436 default:
5437 zig_unreachable();
5438 }
5439 return ir_lval_wrap(ag, scope, result, lval, result_loc);
5440 }
5441 case BuiltinFnIdHasDecl:
5442 {
5443 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5444 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5445 if (arg0_value == ag->codegen->invalid_inst_src)
5446 return arg0_value;
5447
5448 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5449 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5450 if (arg1_value == ag->codegen->invalid_inst_src)
5451 return arg1_value;
5452
5453 Stage1ZirInst *has_decl = ir_build_has_decl(ag, scope, node, arg0_value, arg1_value);
5454 return ir_lval_wrap(ag, scope, has_decl, lval, result_loc);
5455 }
5456 case BuiltinFnIdUnionInit:
5457 {
5458 AstNode *union_type_node = node->data.fn_call_expr.params.at(0);
5459 Stage1ZirInst *union_type_inst = astgen_node(ag, union_type_node, scope);
5460 if (union_type_inst == ag->codegen->invalid_inst_src)
5461 return union_type_inst;
5462
5463 AstNode *name_node = node->data.fn_call_expr.params.at(1);
5464 Stage1ZirInst *name_inst = astgen_node(ag, name_node, scope);
5465 if (name_inst == ag->codegen->invalid_inst_src)
5466 return name_inst;
5467
5468 AstNode *init_node = node->data.fn_call_expr.params.at(2);
5469
5470 return astgen_union_init_expr(ag, scope, node, union_type_inst, name_inst, init_node,
5471 lval, result_loc);
5472 }
5473 case BuiltinFnIdSrc:
5474 {
5475 Stage1ZirInst *src_inst = ir_build_src(ag, scope, node);
5476 return ir_lval_wrap(ag, scope, src_inst, lval, result_loc);
5477 }
5478 case BuiltinFnIdPrefetch:
5479 {
5480 ZigType *options_type = get_builtin_type(ag->codegen, "PrefetchOptions");
5481 Stage1ZirInst *options_type_inst = ir_build_const_type(ag, scope, node, options_type);
5482 ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc());
5483
5484 AstNode *ptr_node = node->data.fn_call_expr.params.at(0);
5485 Stage1ZirInst *ptr_value = astgen_node(ag, ptr_node, scope);
5486 if (ptr_value == ag->codegen->invalid_inst_src)
5487 return ptr_value;
5488
5489 AstNode *options_node = node->data.fn_call_expr.params.at(1);
5490 Stage1ZirInst *options_value = astgen_node_extra(ag, options_node,
5491 scope, LValNone, &result_loc_cast->base);
5492 if (options_value == ag->codegen->invalid_inst_src)
5493 return options_value;
5494
5495 Stage1ZirInst *casted_options_value = ir_build_implicit_cast(
5496 ag, scope, options_node, options_value, result_loc_cast);
5497
5498 Stage1ZirInst *ir_extern = ir_build_prefetch(ag, scope, node, ptr_value, casted_options_value);
5499 return ir_lval_wrap(ag, scope, ir_extern, lval, result_loc);
5500 }
5501 case BuiltinFnIdAddrSpaceCast:
5502 {
5503 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5504 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, scope);
5505 if (arg0_value == ag->codegen->invalid_inst_src)
5506 return arg0_value;
5507
5508 AstNode* arg1_node = node->data.fn_call_expr.params.at(1);
5509 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
5510 if (arg1_value == ag->codegen->invalid_inst_src)
5511 return arg1_value;
5512
5513 Stage1ZirInst *addrspace_cast = ir_build_addrspace_cast(ag, scope, node, arg0_value, arg1_value);
5514 return ir_lval_wrap(ag, scope, addrspace_cast, lval, result_loc);
5515 }
5516 }
5517 zig_unreachable();
5518}
5519
5520static ScopeNoSuspend *get_scope_nosuspend(Scope *scope) {
5521 while (scope) {
5522 if (scope->id == ScopeIdNoSuspend)
5523 return (ScopeNoSuspend *)scope;
5524 if (scope->id == ScopeIdFnDef)
5525 return nullptr;
5526
5527 scope = scope->parent;
5528 }
5529 return nullptr;
5530}
5531
5532static Stage1ZirInst *astgen_fn_call(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval,
5533 ResultLoc *result_loc)
5534{
5535 assert(node->type == NodeTypeFnCallExpr);
5536
5537 if (node->data.fn_call_expr.modifier == CallModifierBuiltin)
5538 return astgen_builtin_fn_call(ag, scope, node, lval, result_loc);
5539
5540 bool is_nosuspend = get_scope_nosuspend(scope) != nullptr;
5541 CallModifier modifier = node->data.fn_call_expr.modifier;
5542 if (is_nosuspend && modifier != CallModifierAsync) {
5543 modifier = CallModifierNoSuspend;
5544 }
5545
5546 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
5547 return astgen_fn_call_with_args(ag, scope, node, fn_ref_node, modifier,
5548 nullptr, node->data.fn_call_expr.params.items, node->data.fn_call_expr.params.length, lval, result_loc);
5549}
5550
5551static Stage1ZirInst *astgen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval,
5552 ResultLoc *result_loc)
5553{
5554 assert(node->type == NodeTypeIfBoolExpr);
5555
5556 Stage1ZirInst *condition = astgen_node(ag, node->data.if_bool_expr.condition, scope);
5557 if (condition == ag->codegen->invalid_inst_src)
5558 return ag->codegen->invalid_inst_src;
5559
5560 Stage1ZirInst *is_comptime;
5561 if (ir_should_inline(ag->exec, scope)) {
5562 is_comptime = ir_build_const_bool(ag, scope, node, true);
5563 } else {
5564 is_comptime = ir_build_test_comptime(ag, scope, node, condition);
5565 }
5566
5567 AstNode *then_node = node->data.if_bool_expr.then_block;
5568 AstNode *else_node = node->data.if_bool_expr.else_node;
5569
5570 Stage1ZirBasicBlock *then_block = ir_create_basic_block(ag, scope, "Then");
5571 Stage1ZirBasicBlock *else_block = ir_create_basic_block(ag, scope, "Else");
5572 Stage1ZirBasicBlock *endif_block = ir_create_basic_block(ag, scope, "EndIf");
5573
5574 Stage1ZirInst *cond_br_inst = ir_build_cond_br(ag, scope, node, condition,
5575 then_block, else_block, is_comptime);
5576 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, else_block, endif_block,
5577 result_loc, is_comptime);
5578
5579 ir_set_cursor_at_end_and_append_block(ag, then_block);
5580
5581 Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime);
5582 Stage1ZirInst *then_expr_result = astgen_node_extra(ag, then_node, subexpr_scope, lval,
5583 &peer_parent->peers.at(0)->base);
5584 if (then_expr_result == ag->codegen->invalid_inst_src)
5585 return ag->codegen->invalid_inst_src;
5586 Stage1ZirBasicBlock *after_then_block = ag->current_basic_block;
5587 if (!instr_is_unreachable(then_expr_result))
5588 ir_build_br(ag, scope, node, endif_block, is_comptime);
5589
5590 ir_set_cursor_at_end_and_append_block(ag, else_block);
5591 Stage1ZirInst *else_expr_result;
5592 if (else_node) {
5593 else_expr_result = astgen_node_extra(ag, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base);
5594 if (else_expr_result == ag->codegen->invalid_inst_src)
5595 return ag->codegen->invalid_inst_src;
5596 } else {
5597 else_expr_result = ir_build_const_void(ag, scope, node);
5598 ir_build_end_expr(ag, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
5599 }
5600 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
5601 if (!instr_is_unreachable(else_expr_result))
5602 ir_build_br(ag, scope, node, endif_block, is_comptime);
5603
5604 ir_set_cursor_at_end_and_append_block(ag, endif_block);
5605 Stage1ZirInst **incoming_values = heap::c_allocator.allocate<Stage1ZirInst *>(2);
5606 incoming_values[0] = then_expr_result;
5607 incoming_values[1] = else_expr_result;
5608 Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2);
5609 incoming_blocks[0] = after_then_block;
5610 incoming_blocks[1] = after_else_block;
5611
5612 Stage1ZirInst *phi = ir_build_phi(ag, scope, node, false, 2, incoming_blocks, incoming_values, peer_parent);
5613 return ir_expr_wrap(ag, scope, phi, result_loc);
5614}
5615
5616static Stage1ZirInst *astgen_prefix_op_id_lval(Stage1AstGen *ag, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) {
5617 assert(node->type == NodeTypePrefixOpExpr);
5618 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
5619
5620 Stage1ZirInst *value = astgen_node_extra(ag, expr_node, scope, lval, nullptr);
5621 if (value == ag->codegen->invalid_inst_src)
5622 return value;
5623
5624 return ir_build_un_op(ag, scope, node, op_id, value);
5625}
5626
5627static Stage1ZirInst *astgen_prefix_op_id(Stage1AstGen *ag, Scope *scope, AstNode *node, IrUnOp op_id) {
5628 return astgen_prefix_op_id_lval(ag, scope, node, op_id, LValNone);
5629}
5630
5631static Stage1ZirInst *ir_expr_wrap(Stage1AstGen *ag, Scope *scope, Stage1ZirInst *inst, ResultLoc *result_loc) {
5632 if (inst == ag->codegen->invalid_inst_src) return inst;
5633 ir_build_end_expr(ag, scope, inst->source_node, inst, result_loc);
5634 return inst;
5635}
5636
5637static Stage1ZirInst *ir_lval_wrap(Stage1AstGen *ag, Scope *scope, Stage1ZirInst *value, LVal lval,
5638 ResultLoc *result_loc)
5639{
5640 // This logic must be kept in sync with
5641 // [STMT_EXPR_TEST_THING] <--- (search this token)
5642 if (value == ag->codegen->invalid_inst_src ||
5643 instr_is_unreachable(value) ||
5644 value->source_node->type == NodeTypeDefer ||
5645 value->id == Stage1ZirInstIdDeclVar)
5646 {
5647 return value;
5648 }
5649
5650 assert(lval != LValAssign);
5651 if (lval == LValPtr) {
5652 // We needed a pointer to a value, but we got a value. So we create
5653 // an instruction which just makes a pointer of it.
5654 return ir_build_ref_src(ag, scope, value->source_node, value);
5655 } else if (result_loc != nullptr) {
5656 return ir_expr_wrap(ag, scope, value, result_loc);
5657 } else {
5658 return value;
5659 }
5660
5661}
5662
5663static PtrLen star_token_to_ptr_len(TokenId token_id) {
5664 switch (token_id) {
5665 case TokenIdStar:
5666 case TokenIdStarStar:
5667 return PtrLenSingle;
5668 case TokenIdLBracket:
5669 return PtrLenUnknown;
5670 case TokenIdIdentifier:
5671 return PtrLenC;
5672 default:
5673 zig_unreachable();
5674 }
5675}
5676
5677static Error token_number_literal_u32(Stage1AstGen *ag, AstNode *source_node,
5678 RootStruct *root_struct, uint32_t *result, TokenIndex token)
5679{
5680 BigInt bigint;
5681 token_number_literal_bigint(root_struct, &bigint, token);
5682
5683 if (!bigint_fits_in_bits(&bigint, 32, false)) {
5684 Buf *val_buf = buf_alloc();
5685 bigint_append_buf(val_buf, &bigint, 10);
5686 exec_add_error_node(ag->codegen, ag->exec, source_node,
5687 buf_sprintf("value %s too large for u32", buf_ptr(val_buf)));
5688 bigint_deinit(&bigint);
5689 return ErrorSemanticAnalyzeFail;
5690 }
5691 *result = bigint_as_u32(&bigint);
5692 bigint_deinit(&bigint);
5693 return ErrorNone;
5694
5695}
5696
5697static Stage1ZirInst *astgen_pointer_type(Stage1AstGen *ag, Scope *scope, AstNode *node) {
5698 Error err;
5699 assert(node->type == NodeTypePointerType);
5700
5701 RootStruct *root_struct = node->owner->data.structure.root_struct;
5702 TokenId star_tok_id = root_struct->token_ids[node->data.pointer_type.star_token];
5703 PtrLen ptr_len = star_token_to_ptr_len(star_tok_id);
5704
5705 bool is_const = node->data.pointer_type.is_const;
5706 bool is_volatile = node->data.pointer_type.is_volatile;
5707 bool is_allow_zero = node->data.pointer_type.allow_zero_token != 0;
5708 AstNode *sentinel_expr = node->data.pointer_type.sentinel;
5709 AstNode *expr_node = node->data.pointer_type.op_expr;
5710 AstNode *align_expr = node->data.pointer_type.align_expr;
5711
5712 Stage1ZirInst *sentinel;
5713 if (sentinel_expr != nullptr) {
5714 sentinel = astgen_node(ag, sentinel_expr, scope);
5715 if (sentinel == ag->codegen->invalid_inst_src)
5716 return sentinel;
5717 } else {
5718 sentinel = nullptr;
5719 }
5720
5721 Stage1ZirInst *align_value;
5722 if (align_expr != nullptr) {
5723 align_value = astgen_node(ag, align_expr, scope);
5724 if (align_value == ag->codegen->invalid_inst_src)
5725 return align_value;
5726 } else {
5727 align_value = nullptr;
5728 }
5729
5730 Stage1ZirInst *child_type = astgen_node(ag, expr_node, scope);
5731 if (child_type == ag->codegen->invalid_inst_src)
5732 return child_type;
5733
5734 uint32_t bit_offset_start = 0;
5735 if (node->data.pointer_type.bit_offset_start != 0) {
5736 if ((err = token_number_literal_u32(ag, node, root_struct, &bit_offset_start,
5737 node->data.pointer_type.bit_offset_start)))
5738 {
5739 return ag->codegen->invalid_inst_src;
5740 }
5741 }
5742
5743 uint32_t host_int_bytes = 0;
5744 if (node->data.pointer_type.host_int_bytes != 0) {
5745 if ((err = token_number_literal_u32(ag, node, root_struct, &host_int_bytes,
5746 node->data.pointer_type.host_int_bytes)))
5747 {
5748 return ag->codegen->invalid_inst_src;
5749 }
5750 }
5751
5752 if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) {
5753 exec_add_error_node(ag->codegen, ag->exec, node,
5754 buf_sprintf("bit offset starts after end of host integer"));
5755 return ag->codegen->invalid_inst_src;
5756 }
5757
5758 return ir_build_ptr_type(ag, scope, node, child_type, is_const, is_volatile,
5759 ptr_len, sentinel, align_value, bit_offset_start, host_int_bytes, is_allow_zero);
5760}
5761
5762static Stage1ZirInst *astgen_catch_unreachable(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
5763 AstNode *expr_node, LVal lval, ResultLoc *result_loc)
5764{
5765 Stage1ZirInst *err_union_ptr = astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr);
5766 if (err_union_ptr == ag->codegen->invalid_inst_src)
5767 return ag->codegen->invalid_inst_src;
5768
5769 Stage1ZirInst *payload_ptr = ir_build_unwrap_err_payload_src(ag, scope, source_node, err_union_ptr, true, false);
5770 if (payload_ptr == ag->codegen->invalid_inst_src)
5771 return ag->codegen->invalid_inst_src;
5772
5773 if (lval == LValPtr)
5774 return payload_ptr;
5775
5776 Stage1ZirInst *load_ptr = ir_build_load_ptr(ag, scope, source_node, payload_ptr);
5777 return ir_expr_wrap(ag, scope, load_ptr, result_loc);
5778}
5779
5780static Stage1ZirInst *astgen_bool_not(Stage1AstGen *ag, Scope *scope, AstNode *node) {
5781 assert(node->type == NodeTypePrefixOpExpr);
5782 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
5783
5784 Stage1ZirInst *value = astgen_node(ag, expr_node, scope);
5785 if (value == ag->codegen->invalid_inst_src)
5786 return ag->codegen->invalid_inst_src;
5787
5788 return ir_build_bool_not(ag, scope, node, value);
5789}
5790
5791static Stage1ZirInst *astgen_prefix_op_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval,
5792 ResultLoc *result_loc)
5793{
5794 assert(node->type == NodeTypePrefixOpExpr);
5795
5796 PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;
5797
5798 switch (prefix_op) {
5799 case PrefixOpInvalid:
5800 zig_unreachable();
5801 case PrefixOpBoolNot:
5802 return ir_lval_wrap(ag, scope, astgen_bool_not(ag, scope, node), lval, result_loc);
5803 case PrefixOpBinNot:
5804 return ir_lval_wrap(ag, scope, astgen_prefix_op_id(ag, scope, node, IrUnOpBinNot), lval, result_loc);
5805 case PrefixOpNegation:
5806 return ir_lval_wrap(ag, scope, astgen_prefix_op_id(ag, scope, node, IrUnOpNegation), lval, result_loc);
5807 case PrefixOpNegationWrap:
5808 return ir_lval_wrap(ag, scope, astgen_prefix_op_id(ag, scope, node, IrUnOpNegationWrap), lval, result_loc);
5809 case PrefixOpOptional:
5810 return ir_lval_wrap(ag, scope, astgen_prefix_op_id(ag, scope, node, IrUnOpOptional), lval, result_loc);
5811 case PrefixOpAddrOf: {
5812 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
5813 return ir_lval_wrap(ag, scope, astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr), lval, result_loc);
5814 }
5815 }
5816 zig_unreachable();
5817}
5818
5819static Stage1ZirInst *astgen_union_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
5820 Stage1ZirInst *union_type, Stage1ZirInst *field_name, AstNode *expr_node,
5821 LVal lval, ResultLoc *parent_result_loc)
5822{
5823 Stage1ZirInst *container_ptr = ir_build_resolve_result(ag, scope, source_node, parent_result_loc, union_type);
5824 Stage1ZirInst *field_ptr = ir_build_field_ptr_instruction(ag, scope, source_node, container_ptr,
5825 field_name, true);
5826
5827 ResultLocInstruction *result_loc_inst = heap::c_allocator.create<ResultLocInstruction>();
5828 result_loc_inst->base.id = ResultLocIdInstruction;
5829 result_loc_inst->base.source_instruction = field_ptr;
5830 ir_ref_instruction(field_ptr, ag->current_basic_block);
5831 ir_build_reset_result(ag, scope, expr_node, &result_loc_inst->base);
5832
5833 Stage1ZirInst *expr_value = astgen_node_extra(ag, expr_node, scope, LValNone,
5834 &result_loc_inst->base);
5835 if (expr_value == ag->codegen->invalid_inst_src)
5836 return expr_value;
5837
5838 Stage1ZirInst *init_union = ir_build_union_init_named_field(ag, scope, source_node, union_type,
5839 field_name, field_ptr, container_ptr);
5840
5841 return ir_lval_wrap(ag, scope, init_union, lval, parent_result_loc);
5842}
5843
5844static Stage1ZirInst *astgen_container_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval,
5845 ResultLoc *parent_result_loc)
5846{
5847 assert(node->type == NodeTypeContainerInitExpr);
5848
5849 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
5850 ContainerInitKind kind = container_init_expr->kind;
5851
5852 ResultLocCast *result_loc_cast = nullptr;
5853 ResultLoc *child_result_loc;
5854 AstNode *init_array_type_source_node;
5855 if (container_init_expr->type != nullptr) {
5856 Stage1ZirInst *container_type;
5857 if (container_init_expr->type->type == NodeTypeInferredArrayType) {
5858 if (kind == ContainerInitKindStruct) {
5859 add_node_error(ag->codegen, container_init_expr->type,
5860 buf_sprintf("initializing array with struct syntax"));
5861 return ag->codegen->invalid_inst_src;
5862 }
5863 Stage1ZirInst *sentinel;
5864 if (container_init_expr->type->data.inferred_array_type.sentinel != nullptr) {
5865 sentinel = astgen_node(ag, container_init_expr->type->data.inferred_array_type.sentinel, scope);
5866 if (sentinel == ag->codegen->invalid_inst_src)
5867 return sentinel;
5868 } else {
5869 sentinel = nullptr;
5870 }
5871
5872 Stage1ZirInst *elem_type = astgen_node(ag,
5873 container_init_expr->type->data.inferred_array_type.child_type, scope);
5874 if (elem_type == ag->codegen->invalid_inst_src)
5875 return elem_type;
5876 size_t item_count = container_init_expr->entries.length;
5877 Stage1ZirInst *item_count_inst = ir_build_const_usize(ag, scope, node, item_count);
5878 container_type = ir_build_array_type(ag, scope, node, item_count_inst, sentinel, elem_type);
5879 } else {
5880 container_type = astgen_node(ag, container_init_expr->type, scope);
5881 if (container_type == ag->codegen->invalid_inst_src)
5882 return container_type;
5883 }
5884
5885 result_loc_cast = ir_build_cast_result_loc(ag, container_type, parent_result_loc);
5886 child_result_loc = &result_loc_cast->base;
5887 init_array_type_source_node = container_type->source_node;
5888 } else {
5889 child_result_loc = parent_result_loc;
5890 if (parent_result_loc->source_instruction != nullptr) {
5891 init_array_type_source_node = parent_result_loc->source_instruction->source_node;
5892 } else {
5893 init_array_type_source_node = node;
5894 }
5895 }
5896
5897 switch (kind) {
5898 case ContainerInitKindStruct: {
5899 Stage1ZirInst *container_ptr = ir_build_resolve_result(ag, scope, node, child_result_loc,
5900 nullptr);
5901
5902 size_t field_count = container_init_expr->entries.length;
5903 Stage1ZirInstContainerInitFieldsField *fields = heap::c_allocator.allocate<Stage1ZirInstContainerInitFieldsField>(field_count);
5904 for (size_t i = 0; i < field_count; i += 1) {
5905 AstNode *entry_node = container_init_expr->entries.at(i);
5906 assert(entry_node->type == NodeTypeStructValueField);
5907
5908 Buf *name = entry_node->data.struct_val_field.name;
5909 AstNode *expr_node = entry_node->data.struct_val_field.expr;
5910
5911 Stage1ZirInst *field_ptr = ir_build_field_ptr(ag, scope, entry_node, container_ptr, name, true);
5912 ResultLocInstruction *result_loc_inst = heap::c_allocator.create<ResultLocInstruction>();
5913 result_loc_inst->base.id = ResultLocIdInstruction;
5914 result_loc_inst->base.source_instruction = field_ptr;
5915 result_loc_inst->base.allow_write_through_const = true;
5916 ir_ref_instruction(field_ptr, ag->current_basic_block);
5917 ir_build_reset_result(ag, scope, expr_node, &result_loc_inst->base);
5918
5919 Stage1ZirInst *expr_value = astgen_node_extra(ag, expr_node, scope, LValNone,
5920 &result_loc_inst->base);
5921 if (expr_value == ag->codegen->invalid_inst_src)
5922 return expr_value;
5923
5924 fields[i].name = name;
5925 fields[i].source_node = entry_node;
5926 fields[i].result_loc = field_ptr;
5927 }
5928 Stage1ZirInst *result = ir_build_container_init_fields(ag, scope, node, field_count,
5929 fields, container_ptr);
5930
5931 if (result_loc_cast != nullptr) {
5932 result = ir_build_implicit_cast(ag, scope, node, result, result_loc_cast);
5933 }
5934 return ir_lval_wrap(ag, scope, result, lval, parent_result_loc);
5935 }
5936 case ContainerInitKindArray: {
5937 size_t item_count = container_init_expr->entries.length;
5938
5939 Stage1ZirInst *container_ptr = ir_build_resolve_result(ag, scope, node, child_result_loc,
5940 nullptr);
5941
5942 Stage1ZirInst **result_locs = heap::c_allocator.allocate<Stage1ZirInst *>(item_count);
5943 for (size_t i = 0; i < item_count; i += 1) {
5944 AstNode *expr_node = container_init_expr->entries.at(i);
5945
5946 Stage1ZirInst *elem_index = ir_build_const_usize(ag, scope, expr_node, i);
5947 Stage1ZirInst *elem_ptr = ir_build_elem_ptr(ag, scope, expr_node, container_ptr,
5948 elem_index, false, PtrLenSingle, init_array_type_source_node);
5949 ResultLocInstruction *result_loc_inst = heap::c_allocator.create<ResultLocInstruction>();
5950 result_loc_inst->base.id = ResultLocIdInstruction;
5951 result_loc_inst->base.source_instruction = elem_ptr;
5952 result_loc_inst->base.allow_write_through_const = true;
5953 ir_ref_instruction(elem_ptr, ag->current_basic_block);
5954 ir_build_reset_result(ag, scope, expr_node, &result_loc_inst->base);
5955
5956 Stage1ZirInst *expr_value = astgen_node_extra(ag, expr_node, scope, LValNone,
5957 &result_loc_inst->base);
5958 if (expr_value == ag->codegen->invalid_inst_src)
5959 return expr_value;
5960
5961 result_locs[i] = elem_ptr;
5962 }
5963 Stage1ZirInst *result = ir_build_container_init_list(ag, scope, node, item_count,
5964 result_locs, container_ptr, init_array_type_source_node);
5965 if (result_loc_cast != nullptr) {
5966 result = ir_build_implicit_cast(ag, scope, node, result, result_loc_cast);
5967 }
5968 return ir_lval_wrap(ag, scope, result, lval, parent_result_loc);
5969 }
5970 }
5971 zig_unreachable();
5972}
5973
5974static ResultLocVar *ir_build_var_result_loc(Stage1AstGen *ag, Stage1ZirInst *alloca, ZigVar *var) {
5975 ResultLocVar *result_loc_var = heap::c_allocator.create<ResultLocVar>();
5976 result_loc_var->base.id = ResultLocIdVar;
5977 result_loc_var->base.source_instruction = alloca;
5978 result_loc_var->base.allow_write_through_const = true;
5979 result_loc_var->var = var;
5980
5981 ir_build_reset_result(ag, alloca->scope, alloca->source_node, &result_loc_var->base);
5982
5983 return result_loc_var;
5984}
5985
5986static ResultLocCast *ir_build_cast_result_loc(Stage1AstGen *ag, Stage1ZirInst *dest_type,
5987 ResultLoc *parent_result_loc)
5988{
5989 ResultLocCast *result_loc_cast = heap::c_allocator.create<ResultLocCast>();
5990 result_loc_cast->base.id = ResultLocIdCast;
5991 result_loc_cast->base.source_instruction = dest_type;
5992 result_loc_cast->base.allow_write_through_const = parent_result_loc->allow_write_through_const;
5993 ir_ref_instruction(dest_type, ag->current_basic_block);
5994 result_loc_cast->parent = parent_result_loc;
5995
5996 ir_build_reset_result(ag, dest_type->scope, dest_type->source_node, &result_loc_cast->base);
5997
5998 return result_loc_cast;
5999}
6000
6001static void build_decl_var_and_init(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigVar *var,
6002 Stage1ZirInst *init, const char *name_hint, Stage1ZirInst *is_comptime)
6003{
6004 Stage1ZirInst *alloca = ir_build_alloca_src(ag, scope, source_node, nullptr, name_hint, is_comptime);
6005 ResultLocVar *var_result_loc = ir_build_var_result_loc(ag, alloca, var);
6006 ir_build_end_expr(ag, scope, source_node, init, &var_result_loc->base);
6007 ir_build_var_decl_src(ag, scope, source_node, var, nullptr, alloca);
6008}
6009
6010static Stage1ZirInst *astgen_var_decl(Stage1AstGen *ag, Scope *scope, AstNode *node) {
6011 assert(node->type == NodeTypeVariableDeclaration);
6012
6013 AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration;
6014
6015 if (buf_eql_str(variable_declaration->symbol, "_")) {
6016 add_node_error(ag->codegen, node, buf_sprintf("`_` is not a declarable symbol"));
6017 return ag->codegen->invalid_inst_src;
6018 }
6019
6020 // Used for the type expr and the align expr
6021 Scope *comptime_scope = create_comptime_scope(ag->codegen, node, scope);
6022
6023 Stage1ZirInst *type_instruction;
6024 if (variable_declaration->type != nullptr) {
6025 type_instruction = astgen_node(ag, variable_declaration->type, comptime_scope);
6026 if (type_instruction == ag->codegen->invalid_inst_src)
6027 return type_instruction;
6028 } else {
6029 type_instruction = nullptr;
6030 }
6031
6032 bool is_shadowable = false;
6033 bool is_const = variable_declaration->is_const;
6034 bool is_extern = variable_declaration->is_extern;
6035
6036 bool is_comptime_scalar = ir_should_inline(ag->exec, scope) || variable_declaration->is_comptime;
6037 Stage1ZirInst *is_comptime = ir_build_const_bool(ag, scope, node, is_comptime_scalar);
6038 ZigVar *var = ir_create_var(ag, node, scope, variable_declaration->symbol,
6039 is_const, is_const, is_shadowable, is_comptime);
6040 // we detect Stage1ZirInstDeclVar in gen_block to make sure the next node
6041 // is inside var->child_scope
6042
6043 if (!is_extern && !variable_declaration->expr) {
6044 var->var_type = ag->codegen->builtin_types.entry_invalid;
6045 add_node_error(ag->codegen, node, buf_sprintf("variables must be initialized"));
6046 return ag->codegen->invalid_inst_src;
6047 }
6048
6049 Stage1ZirInst *align_value = nullptr;
6050 if (variable_declaration->align_expr != nullptr) {
6051 align_value = astgen_node(ag, variable_declaration->align_expr, comptime_scope);
6052 if (align_value == ag->codegen->invalid_inst_src)
6053 return align_value;
6054 }
6055
6056 if (variable_declaration->section_expr != nullptr) {
6057 add_node_error(ag->codegen, variable_declaration->section_expr,
6058 buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol)));
6059 }
6060
6061 // Parser should ensure that this never happens
6062 assert(variable_declaration->threadlocal_tok == 0);
6063
6064 Stage1ZirInst *alloca = ir_build_alloca_src(ag, scope, node, align_value,
6065 buf_ptr(variable_declaration->symbol), is_comptime);
6066
6067 // Create a result location for the initialization expression.
6068 ResultLocVar *result_loc_var = ir_build_var_result_loc(ag, alloca, var);
6069 ResultLoc *init_result_loc;
6070 ResultLocCast *result_loc_cast;
6071 if (type_instruction != nullptr) {
6072 result_loc_cast = ir_build_cast_result_loc(ag, type_instruction, &result_loc_var->base);
6073 init_result_loc = &result_loc_cast->base;
6074 } else {
6075 result_loc_cast = nullptr;
6076 init_result_loc = &result_loc_var->base;
6077 }
6078
6079 Scope *init_scope = is_comptime_scalar ?
6080 create_comptime_scope(ag->codegen, variable_declaration->expr, scope) : scope;
6081
6082 // Temporarily set the name of the Stage1Zir to the VariableDeclaration
6083 // so that the struct or enum from the init expression inherits the name.
6084 Buf *old_exec_name = ag->exec->name;
6085 ag->exec->name = variable_declaration->symbol;
6086 Stage1ZirInst *init_value = astgen_node_extra(ag, variable_declaration->expr, init_scope,
6087 LValNone, init_result_loc);
6088 ag->exec->name = old_exec_name;
6089
6090 if (init_value == ag->codegen->invalid_inst_src)
6091 return ag->codegen->invalid_inst_src;
6092
6093 if (result_loc_cast != nullptr) {
6094 Stage1ZirInst *implicit_cast = ir_build_implicit_cast(ag, scope, init_value->source_node,
6095 init_value, result_loc_cast);
6096 ir_build_end_expr(ag, scope, node, implicit_cast, &result_loc_var->base);
6097 }
6098
6099 return ir_build_var_decl_src(ag, scope, node, var, align_value, alloca);
6100}
6101
6102static Stage1ZirInst *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval,
6103 ResultLoc *result_loc)
6104{
6105 assert(node->type == NodeTypeWhileExpr);
6106
6107 AstNode *continue_expr_node = node->data.while_expr.continue_expr;
6108 AstNode *else_node = node->data.while_expr.else_node;
6109
6110 Stage1ZirBasicBlock *cond_block = ir_create_basic_block(ag, scope, "WhileCond");
6111 Stage1ZirBasicBlock *body_block = ir_create_basic_block(ag, scope, "WhileBody");
6112 Stage1ZirBasicBlock *continue_block = continue_expr_node ?
6113 ir_create_basic_block(ag, scope, "WhileContinue") : cond_block;
6114 Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, scope, "WhileEnd");
6115 Stage1ZirBasicBlock *else_block = else_node ?
6116 ir_create_basic_block(ag, scope, "WhileElse") : end_block;
6117
6118 Stage1ZirInst *is_comptime = ir_build_const_bool(ag, scope, node,
6119 ir_should_inline(ag->exec, scope) || node->data.while_expr.is_inline);
6120 ir_build_br(ag, scope, node, cond_block, is_comptime);
6121
6122 Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime);
6123 Buf *var_symbol = node->data.while_expr.var_symbol;
6124 Buf *err_symbol = node->data.while_expr.err_symbol;
6125 if (err_symbol != nullptr) {
6126 ir_set_cursor_at_end_and_append_block(ag, cond_block);
6127
6128 Scope *payload_scope;
6129 AstNode *symbol_node = node; // TODO make more accurate
6130 ZigVar *payload_var;
6131 if (var_symbol) {
6132 // TODO make it an error to write to payload variable
6133 payload_var = ir_create_var(ag, symbol_node, subexpr_scope, var_symbol,
6134 true, false, false, is_comptime);
6135 payload_scope = payload_var->child_scope;
6136 } else {
6137 payload_scope = subexpr_scope;
6138 }
6139 ScopeExpr *spill_scope = create_expr_scope(ag->codegen, node, payload_scope);
6140 Stage1ZirInst *err_val_ptr = astgen_node_extra(ag, node->data.while_expr.condition, subexpr_scope,
6141 LValPtr, nullptr);
6142 if (err_val_ptr == ag->codegen->invalid_inst_src)
6143 return err_val_ptr;
6144 Stage1ZirInst *is_err = ir_build_test_err_src(ag, scope, node->data.while_expr.condition, err_val_ptr,
6145 true, false);
6146 Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block;
6147 Stage1ZirInst *void_else_result = else_node ? nullptr : ir_build_const_void(ag, scope, node);
6148 Stage1ZirInst *cond_br_inst;
6149 if (!instr_is_unreachable(is_err)) {
6150 cond_br_inst = ir_build_cond_br(ag, scope, node->data.while_expr.condition, is_err,
6151 else_block, body_block, is_comptime);
6152 } else {
6153 // for the purposes of the source instruction to ir_build_result_peers
6154 cond_br_inst = ag->current_basic_block->instruction_list.last();
6155 }
6156
6157 ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, result_loc,
6158 is_comptime);
6159
6160 ir_set_cursor_at_end_and_append_block(ag, body_block);
6161 if (var_symbol) {
6162 Stage1ZirInst *payload_ptr = ir_build_unwrap_err_payload_src(ag, &spill_scope->base, symbol_node,
6163 err_val_ptr, false, false);
6164 Stage1ZirInst *var_value = node->data.while_expr.var_is_ptr ?
6165 payload_ptr : ir_build_load_ptr(ag, &spill_scope->base, symbol_node, payload_ptr);
6166 build_decl_var_and_init(ag, payload_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime);
6167 }
6168
6169 ZigList<Stage1ZirInst *> incoming_values = {0};
6170 ZigList<Stage1ZirBasicBlock *> incoming_blocks = {0};
6171
6172 if (is_duplicate_label(ag->codegen, payload_scope, node, node->data.while_expr.name))
6173 return ag->codegen->invalid_inst_src;
6174
6175 ScopeLoop *loop_scope = create_loop_scope(ag->codegen, node, payload_scope);
6176 loop_scope->break_block = end_block;
6177 loop_scope->continue_block = continue_block;
6178 loop_scope->is_comptime = is_comptime;
6179 loop_scope->incoming_blocks = &incoming_blocks;
6180 loop_scope->incoming_values = &incoming_values;
6181 loop_scope->lval = lval;
6182 loop_scope->peer_parent = peer_parent;
6183 loop_scope->spill_scope = spill_scope;
6184
6185 // Note the body block of the loop is not the place that lval and result_loc are used -
6186 // it's actually in break statements, handled similarly to return statements.
6187 // That is why we set those values in loop_scope above and not in this astgen_node call.
6188 Stage1ZirInst *body_result = astgen_node(ag, node->data.while_expr.body, &loop_scope->base);
6189 if (body_result == ag->codegen->invalid_inst_src)
6190 return body_result;
6191
6192 if (loop_scope->name != nullptr && loop_scope->name_used == false) {
6193 add_node_error(ag->codegen, node, buf_sprintf("unused while label"));
6194 }
6195
6196 if (!instr_is_unreachable(body_result)) {
6197 ir_build_check_statement_is_void(ag, payload_scope, node->data.while_expr.body, body_result);
6198 ir_build_br(ag, payload_scope, node, continue_block, is_comptime);
6199 }
6200
6201 if (continue_expr_node) {
6202 ir_set_cursor_at_end_and_append_block(ag, continue_block);
6203 Stage1ZirInst *expr_result = astgen_node(ag, continue_expr_node, payload_scope);
6204 if (expr_result == ag->codegen->invalid_inst_src)
6205 return expr_result;
6206 if (!instr_is_unreachable(expr_result)) {
6207 ir_build_check_statement_is_void(ag, payload_scope, continue_expr_node, expr_result);
6208 ir_build_br(ag, payload_scope, node, cond_block, is_comptime);
6209 }
6210 }
6211
6212 ir_set_cursor_at_end_and_append_block(ag, else_block);
6213 assert(else_node != nullptr);
6214
6215 // TODO make it an error to write to error variable
6216 AstNode *err_symbol_node = else_node; // TODO make more accurate
6217 ZigVar *err_var = ir_create_var(ag, err_symbol_node, scope, err_symbol,
6218 true, false, false, is_comptime);
6219 Scope *err_scope = err_var->child_scope;
6220 Stage1ZirInst *err_ptr = ir_build_unwrap_err_code_src(ag, err_scope, err_symbol_node, err_val_ptr);
6221 Stage1ZirInst *err_value = ir_build_load_ptr(ag, err_scope, err_symbol_node, err_ptr);
6222 build_decl_var_and_init(ag, err_scope, err_symbol_node, err_var, err_value, buf_ptr(err_symbol), is_comptime);
6223
6224 if (peer_parent->peers.length != 0) {
6225 peer_parent->peers.last()->next_bb = else_block;
6226 }
6227 ResultLocPeer *peer_result = create_peer_result(peer_parent);
6228 peer_parent->peers.append(peer_result);
6229 Stage1ZirInst *else_result = astgen_node_extra(ag, else_node, err_scope, lval, &peer_result->base);
6230 if (else_result == ag->codegen->invalid_inst_src)
6231 return else_result;
6232 if (!instr_is_unreachable(else_result))
6233 ir_build_br(ag, scope, node, end_block, is_comptime);
6234 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
6235 ir_set_cursor_at_end_and_append_block(ag, end_block);
6236 if (else_result) {
6237 incoming_blocks.append(after_else_block);
6238 incoming_values.append(else_result);
6239 } else {
6240 incoming_blocks.append(after_cond_block);
6241 incoming_values.append(void_else_result);
6242 }
6243 if (peer_parent->peers.length != 0) {
6244 peer_parent->peers.last()->next_bb = end_block;
6245 }
6246
6247 Stage1ZirInst *phi = ir_build_phi(ag, scope, node, false, incoming_blocks.length,
6248 incoming_blocks.items, incoming_values.items, peer_parent);
6249 return ir_expr_wrap(ag, scope, phi, result_loc);
6250 } else if (var_symbol != nullptr) {
6251 ir_set_cursor_at_end_and_append_block(ag, cond_block);
6252 Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime);
6253 // TODO make it an error to write to payload variable
6254 AstNode *symbol_node = node; // TODO make more accurate
6255
6256 ZigVar *payload_var = ir_create_var(ag, symbol_node, subexpr_scope, var_symbol,
6257 true, false, false, is_comptime);
6258 Scope *child_scope = payload_var->child_scope;
6259 ScopeExpr *spill_scope = create_expr_scope(ag->codegen, node, child_scope);
6260 Stage1ZirInst *maybe_val_ptr = astgen_node_extra(ag, node->data.while_expr.condition, subexpr_scope,
6261 LValPtr, nullptr);
6262 if (maybe_val_ptr == ag->codegen->invalid_inst_src)
6263 return maybe_val_ptr;
6264 Stage1ZirInst *maybe_val = ir_build_load_ptr(ag, scope, node->data.while_expr.condition, maybe_val_ptr);
6265 Stage1ZirInst *is_non_null = ir_build_test_non_null_src(ag, scope, node->data.while_expr.condition, maybe_val);
6266 Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block;
6267 Stage1ZirInst *void_else_result = else_node ? nullptr : ir_build_const_void(ag, scope, node);
6268 Stage1ZirInst *cond_br_inst;
6269 if (!instr_is_unreachable(is_non_null)) {
6270 cond_br_inst = ir_build_cond_br(ag, scope, node->data.while_expr.condition, is_non_null,
6271 body_block, else_block, is_comptime);
6272 } else {
6273 // for the purposes of the source instruction to ir_build_result_peers
6274 cond_br_inst = ag->current_basic_block->instruction_list.last();
6275 }
6276
6277 ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, result_loc,
6278 is_comptime);
6279
6280 ir_set_cursor_at_end_and_append_block(ag, body_block);
6281 Stage1ZirInst *payload_ptr = ir_build_optional_unwrap_ptr(ag, &spill_scope->base, symbol_node, maybe_val_ptr, false);
6282 Stage1ZirInst *var_value = node->data.while_expr.var_is_ptr ?
6283 payload_ptr : ir_build_load_ptr(ag, &spill_scope->base, symbol_node, payload_ptr);
6284 build_decl_var_and_init(ag, child_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime);
6285
6286 ZigList<Stage1ZirInst *> incoming_values = {0};
6287 ZigList<Stage1ZirBasicBlock *> incoming_blocks = {0};
6288
6289 if (is_duplicate_label(ag->codegen, child_scope, node, node->data.while_expr.name))
6290 return ag->codegen->invalid_inst_src;
6291
6292 ScopeLoop *loop_scope = create_loop_scope(ag->codegen, node, child_scope);
6293 loop_scope->break_block = end_block;
6294 loop_scope->continue_block = continue_block;
6295 loop_scope->is_comptime = is_comptime;
6296 loop_scope->incoming_blocks = &incoming_blocks;
6297 loop_scope->incoming_values = &incoming_values;
6298 loop_scope->lval = lval;
6299 loop_scope->peer_parent = peer_parent;
6300 loop_scope->spill_scope = spill_scope;
6301
6302 // Note the body block of the loop is not the place that lval and result_loc are used -
6303 // it's actually in break statements, handled similarly to return statements.
6304 // That is why we set those values in loop_scope above and not in this astgen_node call.
6305 Stage1ZirInst *body_result = astgen_node(ag, node->data.while_expr.body, &loop_scope->base);
6306 if (body_result == ag->codegen->invalid_inst_src)
6307 return body_result;
6308
6309 if (loop_scope->name != nullptr && loop_scope->name_used == false) {
6310 add_node_error(ag->codegen, node, buf_sprintf("unused while label"));
6311 }
6312
6313 if (!instr_is_unreachable(body_result)) {
6314 ir_build_check_statement_is_void(ag, child_scope, node->data.while_expr.body, body_result);
6315 ir_build_br(ag, child_scope, node, continue_block, is_comptime);
6316 }
6317
6318 if (continue_expr_node) {
6319 ir_set_cursor_at_end_and_append_block(ag, continue_block);
6320 Stage1ZirInst *expr_result = astgen_node(ag, continue_expr_node, child_scope);
6321 if (expr_result == ag->codegen->invalid_inst_src)
6322 return expr_result;
6323 if (!instr_is_unreachable(expr_result)) {
6324 ir_build_check_statement_is_void(ag, child_scope, continue_expr_node, expr_result);
6325 ir_build_br(ag, child_scope, node, cond_block, is_comptime);
6326 }
6327 }
6328
6329 Stage1ZirInst *else_result = nullptr;
6330 if (else_node) {
6331 ir_set_cursor_at_end_and_append_block(ag, else_block);
6332
6333 if (peer_parent->peers.length != 0) {
6334 peer_parent->peers.last()->next_bb = else_block;
6335 }
6336 ResultLocPeer *peer_result = create_peer_result(peer_parent);
6337 peer_parent->peers.append(peer_result);
6338 else_result = astgen_node_extra(ag, else_node, scope, lval, &peer_result->base);
6339 if (else_result == ag->codegen->invalid_inst_src)
6340 return else_result;
6341 if (!instr_is_unreachable(else_result))
6342 ir_build_br(ag, scope, node, end_block, is_comptime);
6343 }
6344 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
6345 ir_set_cursor_at_end_and_append_block(ag, end_block);
6346 if (else_result) {
6347 incoming_blocks.append(after_else_block);
6348 incoming_values.append(else_result);
6349 } else {
6350 incoming_blocks.append(after_cond_block);
6351 incoming_values.append(void_else_result);
6352 }
6353 if (peer_parent->peers.length != 0) {
6354 peer_parent->peers.last()->next_bb = end_block;
6355 }
6356
6357 Stage1ZirInst *phi = ir_build_phi(ag, scope, node, false, incoming_blocks.length,
6358 incoming_blocks.items, incoming_values.items, peer_parent);
6359 return ir_expr_wrap(ag, scope, phi, result_loc);
6360 } else {
6361 ir_set_cursor_at_end_and_append_block(ag, cond_block);
6362 Stage1ZirInst *cond_val = astgen_node(ag, node->data.while_expr.condition, scope);
6363 if (cond_val == ag->codegen->invalid_inst_src)
6364 return cond_val;
6365 Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block;
6366 Stage1ZirInst *void_else_result = else_node ? nullptr : ir_build_const_void(ag, scope, node);
6367 Stage1ZirInst *cond_br_inst;
6368 if (!instr_is_unreachable(cond_val)) {
6369 cond_br_inst = ir_build_cond_br(ag, scope, node->data.while_expr.condition, cond_val,
6370 body_block, else_block, is_comptime);
6371 } else {
6372 // for the purposes of the source instruction to ir_build_result_peers
6373 cond_br_inst = ag->current_basic_block->instruction_list.last();
6374 }
6375
6376 ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, result_loc,
6377 is_comptime);
6378 ir_set_cursor_at_end_and_append_block(ag, body_block);
6379
6380 ZigList<Stage1ZirInst *> incoming_values = {0};
6381 ZigList<Stage1ZirBasicBlock *> incoming_blocks = {0};
6382
6383 Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime);
6384
6385 if (is_duplicate_label(ag->codegen, subexpr_scope, node, node->data.while_expr.name))
6386 return ag->codegen->invalid_inst_src;
6387
6388 ScopeLoop *loop_scope = create_loop_scope(ag->codegen, node, subexpr_scope);
6389 loop_scope->break_block = end_block;
6390 loop_scope->continue_block = continue_block;
6391 loop_scope->is_comptime = is_comptime;
6392 loop_scope->incoming_blocks = &incoming_blocks;
6393 loop_scope->incoming_values = &incoming_values;
6394 loop_scope->lval = lval;
6395 loop_scope->peer_parent = peer_parent;
6396
6397 // Note the body block of the loop is not the place that lval and result_loc are used -
6398 // it's actually in break statements, handled similarly to return statements.
6399 // That is why we set those values in loop_scope above and not in this astgen_node call.
6400 Stage1ZirInst *body_result = astgen_node(ag, node->data.while_expr.body, &loop_scope->base);
6401 if (body_result == ag->codegen->invalid_inst_src)
6402 return body_result;
6403
6404 if (loop_scope->name != nullptr && loop_scope->name_used == false) {
6405 add_node_error(ag->codegen, node, buf_sprintf("unused while label"));
6406 }
6407
6408 if (!instr_is_unreachable(body_result)) {
6409 ir_build_check_statement_is_void(ag, scope, node->data.while_expr.body, body_result);
6410 ir_build_br(ag, scope, node, continue_block, is_comptime);
6411 }
6412
6413 if (continue_expr_node) {
6414 ir_set_cursor_at_end_and_append_block(ag, continue_block);
6415 Stage1ZirInst *expr_result = astgen_node(ag, continue_expr_node, subexpr_scope);
6416 if (expr_result == ag->codegen->invalid_inst_src)
6417 return expr_result;
6418 if (!instr_is_unreachable(expr_result)) {
6419 ir_build_check_statement_is_void(ag, scope, continue_expr_node, expr_result);
6420 ir_build_br(ag, scope, node, cond_block, is_comptime);
6421 }
6422 }
6423
6424 Stage1ZirInst *else_result = nullptr;
6425 if (else_node) {
6426 ir_set_cursor_at_end_and_append_block(ag, else_block);
6427
6428 if (peer_parent->peers.length != 0) {
6429 peer_parent->peers.last()->next_bb = else_block;
6430 }
6431 ResultLocPeer *peer_result = create_peer_result(peer_parent);
6432 peer_parent->peers.append(peer_result);
6433
6434 else_result = astgen_node_extra(ag, else_node, subexpr_scope, lval, &peer_result->base);
6435 if (else_result == ag->codegen->invalid_inst_src)
6436 return else_result;
6437 if (!instr_is_unreachable(else_result))
6438 ir_build_br(ag, scope, node, end_block, is_comptime);
6439 }
6440 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
6441 ir_set_cursor_at_end_and_append_block(ag, end_block);
6442 if (else_result) {
6443 incoming_blocks.append(after_else_block);
6444 incoming_values.append(else_result);
6445 } else {
6446 incoming_blocks.append(after_cond_block);
6447 incoming_values.append(void_else_result);
6448 }
6449 if (peer_parent->peers.length != 0) {
6450 peer_parent->peers.last()->next_bb = end_block;
6451 }
6452
6453 Stage1ZirInst *phi = ir_build_phi(ag, scope, node, false, incoming_blocks.length,
6454 incoming_blocks.items, incoming_values.items, peer_parent);
6455 return ir_expr_wrap(ag, scope, phi, result_loc);
6456 }
6457}
6458
6459static Stage1ZirInst *astgen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval,
6460 ResultLoc *result_loc)
6461{
6462 assert(node->type == NodeTypeForExpr);
6463
6464 AstNode *array_node = node->data.for_expr.array_expr;
6465 AstNode *elem_node = node->data.for_expr.elem_node;
6466 AstNode *index_node = node->data.for_expr.index_node;
6467 AstNode *body_node = node->data.for_expr.body;
6468 AstNode *else_node = node->data.for_expr.else_node;
6469
6470 if (!elem_node) {
6471 add_node_error(ag->codegen, node, buf_sprintf("for loop expression missing element parameter"));
6472 return ag->codegen->invalid_inst_src;
6473 }
6474 assert(elem_node->type == NodeTypeIdentifier);
6475
6476 ScopeExpr *spill_scope = create_expr_scope(ag->codegen, node, parent_scope);
6477
6478 Stage1ZirInst *array_val_ptr = astgen_node_extra(ag, array_node, &spill_scope->base, LValPtr, nullptr);
6479 if (array_val_ptr == ag->codegen->invalid_inst_src)
6480 return array_val_ptr;
6481
6482 Stage1ZirInst *is_comptime = ir_build_const_bool(ag, parent_scope, node,
6483 ir_should_inline(ag->exec, parent_scope) || node->data.for_expr.is_inline);
6484
6485 AstNode *index_var_source_node;
6486 ZigVar *index_var;
6487 const char *index_var_name;
6488 if (index_node) {
6489 index_var_source_node = index_node;
6490 Buf *index_var_name_buf = node_identifier_buf(index_node);
6491 index_var = ir_create_var(ag, index_node, parent_scope, index_var_name_buf, true, false, false, is_comptime);
6492 index_var_name = buf_ptr(index_var_name_buf);
6493 } else {
6494 index_var_source_node = node;
6495 index_var = ir_create_var(ag, node, parent_scope, nullptr, true, false, true, is_comptime);
6496 index_var_name = "i";
6497 }
6498
6499 Stage1ZirInst *zero = ir_build_const_usize(ag, parent_scope, node, 0);
6500 build_decl_var_and_init(ag, parent_scope, index_var_source_node, index_var, zero, index_var_name, is_comptime);
6501 parent_scope = index_var->child_scope;
6502
6503 Stage1ZirInst *one = ir_build_const_usize(ag, parent_scope, node, 1);
6504 Stage1ZirInst *index_ptr = ir_build_var_ptr(ag, parent_scope, node, index_var);
6505
6506
6507 Stage1ZirBasicBlock *cond_block = ir_create_basic_block(ag, parent_scope, "ForCond");
6508 Stage1ZirBasicBlock *body_block = ir_create_basic_block(ag, parent_scope, "ForBody");
6509 Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, parent_scope, "ForEnd");
6510 Stage1ZirBasicBlock *else_block = else_node ? ir_create_basic_block(ag, parent_scope, "ForElse") : end_block;
6511 Stage1ZirBasicBlock *continue_block = ir_create_basic_block(ag, parent_scope, "ForContinue");
6512
6513 Buf *len_field_name = buf_create_from_str("len");
6514 Stage1ZirInst *len_ref = ir_build_field_ptr(ag, parent_scope, node, array_val_ptr, len_field_name, false);
6515 Stage1ZirInst *len_val = ir_build_load_ptr(ag, &spill_scope->base, node, len_ref);
6516 ir_build_br(ag, parent_scope, node, cond_block, is_comptime);
6517
6518 ir_set_cursor_at_end_and_append_block(ag, cond_block);
6519 Stage1ZirInst *index_val = ir_build_load_ptr(ag, &spill_scope->base, node, index_ptr);
6520 Stage1ZirInst *cond = ir_build_bin_op(ag, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);
6521 Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block;
6522 Stage1ZirInst *void_else_value = else_node ? nullptr : ir_build_const_void(ag, parent_scope, node);
6523 Stage1ZirInst *cond_br_inst = ir_build_cond_br(ag, parent_scope, node, cond,
6524 body_block, else_block, is_comptime);
6525
6526 ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, result_loc, is_comptime);
6527
6528 ir_set_cursor_at_end_and_append_block(ag, body_block);
6529 Stage1ZirInst *elem_ptr = ir_build_elem_ptr(ag, &spill_scope->base, node, array_val_ptr, index_val,
6530 false, PtrLenSingle, nullptr);
6531 // TODO make it an error to write to element variable or i variable.
6532 Buf *elem_var_name = node_identifier_buf(elem_node);
6533 ZigVar *elem_var = ir_create_var(ag, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime);
6534 Scope *child_scope = elem_var->child_scope;
6535
6536 Stage1ZirInst *elem_value = node->data.for_expr.elem_is_ptr ?
6537 elem_ptr : ir_build_load_ptr(ag, &spill_scope->base, elem_node, elem_ptr);
6538 build_decl_var_and_init(ag, parent_scope, elem_node, elem_var, elem_value, buf_ptr(elem_var_name), is_comptime);
6539
6540 if (is_duplicate_label(ag->codegen, child_scope, node, node->data.for_expr.name))
6541 return ag->codegen->invalid_inst_src;
6542
6543 ZigList<Stage1ZirInst *> incoming_values = {0};
6544 ZigList<Stage1ZirBasicBlock *> incoming_blocks = {0};
6545 ScopeLoop *loop_scope = create_loop_scope(ag->codegen, node, child_scope);
6546 loop_scope->break_block = end_block;
6547 loop_scope->continue_block = continue_block;
6548 loop_scope->is_comptime = is_comptime;
6549 loop_scope->incoming_blocks = &incoming_blocks;
6550 loop_scope->incoming_values = &incoming_values;
6551 loop_scope->lval = LValNone;
6552 loop_scope->peer_parent = peer_parent;
6553 loop_scope->spill_scope = spill_scope;
6554
6555 // Note the body block of the loop is not the place that lval and result_loc are used -
6556 // it's actually in break statements, handled similarly to return statements.
6557 // That is why we set those values in loop_scope above and not in this astgen_node call.
6558 Stage1ZirInst *body_result = astgen_node(ag, body_node, &loop_scope->base);
6559 if (body_result == ag->codegen->invalid_inst_src)
6560 return ag->codegen->invalid_inst_src;
6561
6562 if (loop_scope->name != nullptr && loop_scope->name_used == false) {
6563 add_node_error(ag->codegen, node, buf_sprintf("unused for label"));
6564 }
6565
6566 if (!instr_is_unreachable(body_result)) {
6567 ir_build_check_statement_is_void(ag, child_scope, node->data.for_expr.body, body_result);
6568 ir_build_br(ag, child_scope, node, continue_block, is_comptime);
6569 }
6570
6571 ir_set_cursor_at_end_and_append_block(ag, continue_block);
6572 Stage1ZirInst *new_index_val = ir_build_bin_op(ag, child_scope, node, IrBinOpAdd, index_val, one, false);
6573 ir_build_store_ptr(ag, child_scope, node, index_ptr, new_index_val)->allow_write_through_const = true;
6574 ir_build_br(ag, child_scope, node, cond_block, is_comptime);
6575
6576 Stage1ZirInst *else_result = nullptr;
6577 if (else_node) {
6578 ir_set_cursor_at_end_and_append_block(ag, else_block);
6579
6580 if (peer_parent->peers.length != 0) {
6581 peer_parent->peers.last()->next_bb = else_block;
6582 }
6583 ResultLocPeer *peer_result = create_peer_result(peer_parent);
6584 peer_parent->peers.append(peer_result);
6585 else_result = astgen_node_extra(ag, else_node, parent_scope, LValNone, &peer_result->base);
6586 if (else_result == ag->codegen->invalid_inst_src)
6587 return else_result;
6588 if (!instr_is_unreachable(else_result))
6589 ir_build_br(ag, parent_scope, node, end_block, is_comptime);
6590 }
6591 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
6592 ir_set_cursor_at_end_and_append_block(ag, end_block);
6593
6594 if (else_result) {
6595 incoming_blocks.append(after_else_block);
6596 incoming_values.append(else_result);
6597 } else {
6598 incoming_blocks.append(after_cond_block);
6599 incoming_values.append(void_else_value);
6600 }
6601 if (peer_parent->peers.length != 0) {
6602 peer_parent->peers.last()->next_bb = end_block;
6603 }
6604
6605 Stage1ZirInst *phi = ir_build_phi(ag, parent_scope, node, false, incoming_blocks.length,
6606 incoming_blocks.items, incoming_values.items, peer_parent);
6607 return ir_lval_wrap(ag, parent_scope, phi, lval, result_loc);
6608}
6609
6610static Stage1ZirInst *astgen_enum_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) {
6611 assert(node->type == NodeTypeEnumLiteral);
6612 // Currently, stage1 runs astgen for every comptime function call,
6613 // resulting the allocation here wasting memory. As a workaround until
6614 // the code is adjusted to make astgen run only once per source node,
6615 // we memoize the result into the AST here.
6616 if (node->data.enum_literal.name == nullptr) {
6617 RootStruct *root_struct = node->owner->data.structure.root_struct;
6618 node->data.enum_literal.name = token_identifier_buf(root_struct, node->main_token + 1);
6619 }
6620 return ir_build_const_enum_literal(ag, scope, node, node->data.enum_literal.name);
6621}
6622
6623static Stage1ZirInst *astgen_string_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) {
6624 Error err;
6625 assert(node->type == NodeTypeStringLiteral);
6626
6627 RootStruct *root_struct = node->owner->data.structure.root_struct;
6628 const char *source = buf_ptr(root_struct->source_code);
6629
6630 TokenId *token_ids = root_struct->token_ids;
6631
6632 Buf *str = buf_alloc();
6633 if (token_ids[node->main_token] == TokenIdStringLiteral) {
6634 size_t byte_offset = root_struct->token_locs[node->main_token].offset;
6635 size_t bad_index;
6636 if ((err = source_string_literal_buf(source + byte_offset, str, &bad_index))) {
6637 add_token_error_offset(ag->codegen, node->owner, node->main_token,
6638 buf_create_from_str("invalid string literal character"), bad_index);
6639 }
6640 src_assert(source[byte_offset] == '"', node);
6641 byte_offset += 1;
6642 } else if (token_ids[node->main_token] == TokenIdMultilineStringLiteralLine) {
6643 TokenIndex tok_index = node->main_token;
6644 bool first = true;
6645 for (;token_ids[tok_index] == TokenIdMultilineStringLiteralLine; tok_index += 1) {
6646 size_t byte_offset = root_struct->token_locs[tok_index].offset;
6647 size_t end = byte_offset;
6648 while (source[end] != 0 && source[end] != '\n') {
6649 end += 1;
6650 }
6651 if (!first) {
6652 buf_append_char(str, '\n');
6653 } else {
6654 first = false;
6655 }
6656 buf_append_mem(str, source + byte_offset + 2, end - byte_offset - 2);
6657 }
6658 } else {
6659 zig_unreachable();
6660 }
6661
6662 return ir_build_const_str_lit(ag, scope, node, str);
6663}
6664
6665static Stage1ZirInst *astgen_array_type(Stage1AstGen *ag, Scope *scope, AstNode *node) {
6666 assert(node->type == NodeTypeArrayType);
6667
6668 AstNode *size_node = node->data.array_type.size;
6669 AstNode *child_type_node = node->data.array_type.child_type;
6670 bool is_const = node->data.array_type.is_const;
6671 bool is_volatile = node->data.array_type.is_volatile;
6672 bool is_allow_zero = node->data.array_type.allow_zero_token != 0;
6673 AstNode *sentinel_expr = node->data.array_type.sentinel;
6674 AstNode *align_expr = node->data.array_type.align_expr;
6675
6676 Scope *comptime_scope = create_comptime_scope(ag->codegen, node, scope);
6677
6678 Stage1ZirInst *sentinel;
6679 if (sentinel_expr != nullptr) {
6680 sentinel = astgen_node(ag, sentinel_expr, comptime_scope);
6681 if (sentinel == ag->codegen->invalid_inst_src)
6682 return sentinel;
6683 } else {
6684 sentinel = nullptr;
6685 }
6686
6687 if (size_node) {
6688 if (is_const) {
6689 add_node_error(ag->codegen, node, buf_create_from_str("const qualifier invalid on array type"));
6690 return ag->codegen->invalid_inst_src;
6691 }
6692 if (is_volatile) {
6693 add_node_error(ag->codegen, node, buf_create_from_str("volatile qualifier invalid on array type"));
6694 return ag->codegen->invalid_inst_src;
6695 }
6696 if (is_allow_zero) {
6697 add_node_error(ag->codegen, node, buf_create_from_str("allowzero qualifier invalid on array type"));
6698 return ag->codegen->invalid_inst_src;
6699 }
6700 if (align_expr != nullptr) {
6701 add_node_error(ag->codegen, node, buf_create_from_str("align qualifier invalid on array type"));
6702 return ag->codegen->invalid_inst_src;
6703 }
6704
6705 Stage1ZirInst *size_value = astgen_node(ag, size_node, comptime_scope);
6706 if (size_value == ag->codegen->invalid_inst_src)
6707 return size_value;
6708
6709 Stage1ZirInst *child_type = astgen_node(ag, child_type_node, comptime_scope);
6710 if (child_type == ag->codegen->invalid_inst_src)
6711 return child_type;
6712
6713 return ir_build_array_type(ag, scope, node, size_value, sentinel, child_type);
6714 } else {
6715 Stage1ZirInst *align_value;
6716 if (align_expr != nullptr) {
6717 align_value = astgen_node(ag, align_expr, comptime_scope);
6718 if (align_value == ag->codegen->invalid_inst_src)
6719 return align_value;
6720 } else {
6721 align_value = nullptr;
6722 }
6723
6724 Stage1ZirInst *child_type = astgen_node(ag, child_type_node, comptime_scope);
6725 if (child_type == ag->codegen->invalid_inst_src)
6726 return child_type;
6727
6728 return ir_build_slice_type(ag, scope, node, child_type, is_const, is_volatile, sentinel,
6729 align_value, is_allow_zero);
6730 }
6731}
6732
6733static Stage1ZirInst *astgen_anyframe_type(Stage1AstGen *ag, Scope *scope, AstNode *node) {
6734 assert(node->type == NodeTypeAnyFrameType);
6735
6736 AstNode *payload_type_node = node->data.anyframe_type.payload_type;
6737 Stage1ZirInst *payload_type_value = nullptr;
6738
6739 if (payload_type_node != nullptr) {
6740 payload_type_value = astgen_node(ag, payload_type_node, scope);
6741 if (payload_type_value == ag->codegen->invalid_inst_src)
6742 return payload_type_value;
6743
6744 }
6745
6746 return ir_build_anyframe_type(ag, scope, node, payload_type_value);
6747}
6748
6749static Stage1ZirInst *astgen_asm_expr(Stage1AstGen *ag, Scope *scope, AstNode *node) {
6750 assert(node->type == NodeTypeAsmExpr);
6751 AstNodeAsmExpr *asm_expr = &node->data.asm_expr;
6752
6753 Stage1ZirInst *asm_template = astgen_node(ag, asm_expr->asm_template, scope);
6754 if (asm_template == ag->codegen->invalid_inst_src)
6755 return ag->codegen->invalid_inst_src;
6756
6757 bool is_volatile = asm_expr->volatile_token != 0;
6758 bool in_fn_scope = (scope_fn_entry(scope) != nullptr);
6759
6760 if (!in_fn_scope) {
6761 if (is_volatile) {
6762 add_token_error(ag->codegen, node->owner, asm_expr->volatile_token,
6763 buf_sprintf("volatile is meaningless on global assembly"));
6764 return ag->codegen->invalid_inst_src;
6765 }
6766
6767 if (asm_expr->output_list.length != 0 || asm_expr->input_list.length != 0 ||
6768 asm_expr->clobber_list.length != 0)
6769 {
6770 add_node_error(ag->codegen, node,
6771 buf_sprintf("global assembly cannot have inputs, outputs, or clobbers"));
6772 return ag->codegen->invalid_inst_src;
6773 }
6774
6775 return ir_build_asm_src(ag, scope, node, asm_template, nullptr, nullptr,
6776 nullptr, 0, is_volatile, true);
6777 }
6778
6779 Stage1ZirInst **input_list = heap::c_allocator.allocate<Stage1ZirInst *>(asm_expr->input_list.length);
6780 Stage1ZirInst **output_types = heap::c_allocator.allocate<Stage1ZirInst *>(asm_expr->output_list.length);
6781 ZigVar **output_vars = heap::c_allocator.allocate<ZigVar *>(asm_expr->output_list.length);
6782 size_t return_count = 0;
6783 if (!is_volatile && asm_expr->output_list.length == 0) {
6784 add_node_error(ag->codegen, node,
6785 buf_sprintf("assembly expression with no output must be marked volatile"));
6786 return ag->codegen->invalid_inst_src;
6787 }
6788 for (size_t i = 0; i < asm_expr->output_list.length; i += 1) {
6789 AsmOutput *asm_output = asm_expr->output_list.at(i);
6790 if (asm_output->return_type) {
6791 return_count += 1;
6792
6793 Stage1ZirInst *return_type = astgen_node(ag, asm_output->return_type, scope);
6794 if (return_type == ag->codegen->invalid_inst_src)
6795 return ag->codegen->invalid_inst_src;
6796 if (return_count > 1) {
6797 add_node_error(ag->codegen, node,
6798 buf_sprintf("inline assembly allows up to one output value"));
6799 return ag->codegen->invalid_inst_src;
6800 }
6801 output_types[i] = return_type;
6802 } else {
6803 Buf *variable_name = asm_output->variable_name;
6804 // TODO there is some duplication here with astgen_identifier. I need to do a full audit of how
6805 // inline assembly works. https://github.com/ziglang/zig/issues/215
6806 ZigVar *var = find_variable(ag->codegen, scope, variable_name, nullptr);
6807 if (var) {
6808 output_vars[i] = var;
6809 } else {
6810 add_node_error(ag->codegen, node,
6811 buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
6812 return ag->codegen->invalid_inst_src;
6813 }
6814 }
6815
6816 const char modifier = *buf_ptr(asm_output->constraint);
6817 if (modifier != '=') {
6818 add_node_error(ag->codegen, node,
6819 buf_sprintf("invalid modifier starting output constraint for '%s': '%c', only '=' is supported."
6820 " Compiler TODO: see https://github.com/ziglang/zig/issues/215",
6821 buf_ptr(asm_output->asm_symbolic_name), modifier));
6822 return ag->codegen->invalid_inst_src;
6823 }
6824 }
6825 for (size_t i = 0; i < asm_expr->input_list.length; i += 1) {
6826 AsmInput *asm_input = asm_expr->input_list.at(i);
6827 Stage1ZirInst *input_value = astgen_node(ag, asm_input->expr, scope);
6828 if (input_value == ag->codegen->invalid_inst_src)
6829 return ag->codegen->invalid_inst_src;
6830
6831 input_list[i] = input_value;
6832 }
6833
6834 return ir_build_asm_src(ag, scope, node, asm_template, input_list, output_types,
6835 output_vars, return_count, is_volatile, false);
6836}
6837
6838static Stage1ZirInst *astgen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval,
6839 ResultLoc *result_loc)
6840{
6841 assert(node->type == NodeTypeIfOptional);
6842
6843 Buf *var_symbol = node->data.test_expr.var_symbol;
6844 AstNode *expr_node = node->data.test_expr.target_node;
6845 AstNode *then_node = node->data.test_expr.then_node;
6846 AstNode *else_node = node->data.test_expr.else_node;
6847 bool var_is_ptr = node->data.test_expr.var_is_ptr;
6848
6849 ScopeExpr *spill_scope = create_expr_scope(ag->codegen, expr_node, scope);
6850 spill_scope->spill_harder = true;
6851
6852 Stage1ZirInst *maybe_val_ptr = astgen_node_extra(ag, expr_node, &spill_scope->base, LValPtr, nullptr);
6853 if (maybe_val_ptr == ag->codegen->invalid_inst_src)
6854 return maybe_val_ptr;
6855
6856 Stage1ZirInst *maybe_val = ir_build_load_ptr(ag, scope, node, maybe_val_ptr);
6857 Stage1ZirInst *is_non_null = ir_build_test_non_null_src(ag, scope, node, maybe_val);
6858
6859 Stage1ZirBasicBlock *then_block = ir_create_basic_block(ag, scope, "OptionalThen");
6860 Stage1ZirBasicBlock *else_block = ir_create_basic_block(ag, scope, "OptionalElse");
6861 Stage1ZirBasicBlock *endif_block = ir_create_basic_block(ag, scope, "OptionalEndIf");
6862
6863 Stage1ZirInst *is_comptime;
6864 if (ir_should_inline(ag->exec, scope)) {
6865 is_comptime = ir_build_const_bool(ag, scope, node, true);
6866 } else {
6867 is_comptime = ir_build_test_comptime(ag, scope, node, is_non_null);
6868 }
6869 Stage1ZirInst *cond_br_inst = ir_build_cond_br(ag, scope, node, is_non_null,
6870 then_block, else_block, is_comptime);
6871
6872 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, else_block, endif_block,
6873 result_loc, is_comptime);
6874
6875 ir_set_cursor_at_end_and_append_block(ag, then_block);
6876
6877 Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, &spill_scope->base, is_comptime);
6878 Scope *var_scope;
6879 if (var_symbol) {
6880 bool is_shadowable = false;
6881 bool is_const = true;
6882 ZigVar *var = ir_create_var(ag, node, subexpr_scope,
6883 var_symbol, is_const, is_const, is_shadowable, is_comptime);
6884
6885 Stage1ZirInst *payload_ptr = ir_build_optional_unwrap_ptr(ag, subexpr_scope, node, maybe_val_ptr, false);
6886 Stage1ZirInst *var_value = var_is_ptr ?
6887 payload_ptr : ir_build_load_ptr(ag, &spill_scope->base, node, payload_ptr);
6888 build_decl_var_and_init(ag, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), is_comptime);
6889 var_scope = var->child_scope;
6890 } else {
6891 var_scope = subexpr_scope;
6892 }
6893 Stage1ZirInst *then_expr_result = astgen_node_extra(ag, then_node, var_scope, lval,
6894 &peer_parent->peers.at(0)->base);
6895 if (then_expr_result == ag->codegen->invalid_inst_src)
6896 return then_expr_result;
6897 Stage1ZirBasicBlock *after_then_block = ag->current_basic_block;
6898 if (!instr_is_unreachable(then_expr_result))
6899 ir_build_br(ag, scope, node, endif_block, is_comptime);
6900
6901 ir_set_cursor_at_end_and_append_block(ag, else_block);
6902 Stage1ZirInst *else_expr_result;
6903 if (else_node) {
6904 else_expr_result = astgen_node_extra(ag, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base);
6905 if (else_expr_result == ag->codegen->invalid_inst_src)
6906 return else_expr_result;
6907 } else {
6908 else_expr_result = ir_build_const_void(ag, scope, node);
6909 ir_build_end_expr(ag, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
6910 }
6911 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
6912 if (!instr_is_unreachable(else_expr_result))
6913 ir_build_br(ag, scope, node, endif_block, is_comptime);
6914
6915 ir_set_cursor_at_end_and_append_block(ag, endif_block);
6916 Stage1ZirInst **incoming_values = heap::c_allocator.allocate<Stage1ZirInst *>(2);
6917 incoming_values[0] = then_expr_result;
6918 incoming_values[1] = else_expr_result;
6919 Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2);
6920 incoming_blocks[0] = after_then_block;
6921 incoming_blocks[1] = after_else_block;
6922
6923 Stage1ZirInst *phi = ir_build_phi(ag, scope, node, false, 2, incoming_blocks, incoming_values, peer_parent);
6924 return ir_expr_wrap(ag, scope, phi, result_loc);
6925}
6926
6927static Stage1ZirInst *astgen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval,
6928 ResultLoc *result_loc)
6929{
6930 assert(node->type == NodeTypeIfErrorExpr);
6931
6932 AstNode *target_node = node->data.if_err_expr.target_node;
6933 AstNode *then_node = node->data.if_err_expr.then_node;
6934 AstNode *else_node = node->data.if_err_expr.else_node;
6935 bool var_is_ptr = node->data.if_err_expr.var_is_ptr;
6936 bool var_is_const = true;
6937 Buf *var_symbol = node->data.if_err_expr.var_symbol;
6938 Buf *err_symbol = node->data.if_err_expr.err_symbol;
6939
6940 Stage1ZirInst *err_val_ptr = astgen_node_extra(ag, target_node, scope, LValPtr, nullptr);
6941 if (err_val_ptr == ag->codegen->invalid_inst_src)
6942 return err_val_ptr;
6943
6944 Stage1ZirInst *err_val = ir_build_load_ptr(ag, scope, node, err_val_ptr);
6945 Stage1ZirInst *is_err = ir_build_test_err_src(ag, scope, node, err_val_ptr, true, false);
6946
6947 Stage1ZirBasicBlock *ok_block = ir_create_basic_block(ag, scope, "TryOk");
6948 Stage1ZirBasicBlock *else_block = ir_create_basic_block(ag, scope, "TryElse");
6949 Stage1ZirBasicBlock *endif_block = ir_create_basic_block(ag, scope, "TryEnd");
6950
6951 bool force_comptime = ir_should_inline(ag->exec, scope);
6952 Stage1ZirInst *is_comptime = force_comptime ? ir_build_const_bool(ag, scope, node, true) : ir_build_test_comptime(ag, scope, node, is_err);
6953 Stage1ZirInst *cond_br_inst = ir_build_cond_br(ag, scope, node, is_err, else_block, ok_block, is_comptime);
6954
6955 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, else_block, endif_block,
6956 result_loc, is_comptime);
6957
6958 ir_set_cursor_at_end_and_append_block(ag, ok_block);
6959
6960 Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime);
6961 Scope *var_scope;
6962 if (var_symbol) {
6963 bool is_shadowable = false;
6964 Stage1ZirInst *var_is_comptime = force_comptime ? ir_build_const_bool(ag, subexpr_scope, node, true) : ir_build_test_comptime(ag, subexpr_scope, node, err_val);
6965 ZigVar *var = ir_create_var(ag, node, subexpr_scope,
6966 var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime);
6967
6968 Stage1ZirInst *payload_ptr = ir_build_unwrap_err_payload_src(ag, subexpr_scope, node, err_val_ptr, false, false);
6969 Stage1ZirInst *var_value = var_is_ptr ?
6970 payload_ptr : ir_build_load_ptr(ag, subexpr_scope, node, payload_ptr);
6971 build_decl_var_and_init(ag, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), var_is_comptime);
6972 var_scope = var->child_scope;
6973 } else {
6974 var_scope = subexpr_scope;
6975 }
6976 Stage1ZirInst *then_expr_result = astgen_node_extra(ag, then_node, var_scope, lval,
6977 &peer_parent->peers.at(0)->base);
6978 if (then_expr_result == ag->codegen->invalid_inst_src)
6979 return then_expr_result;
6980 Stage1ZirBasicBlock *after_then_block = ag->current_basic_block;
6981 if (!instr_is_unreachable(then_expr_result))
6982 ir_build_br(ag, scope, node, endif_block, is_comptime);
6983
6984 ir_set_cursor_at_end_and_append_block(ag, else_block);
6985
6986 Stage1ZirInst *else_expr_result;
6987 if (else_node) {
6988 Scope *err_var_scope;
6989 if (err_symbol) {
6990 bool is_shadowable = false;
6991 bool is_const = true;
6992 ZigVar *var = ir_create_var(ag, node, subexpr_scope,
6993 err_symbol, is_const, is_const, is_shadowable, is_comptime);
6994
6995 Stage1ZirInst *err_ptr = ir_build_unwrap_err_code_src(ag, subexpr_scope, node, err_val_ptr);
6996 Stage1ZirInst *err_value = ir_build_load_ptr(ag, subexpr_scope, node, err_ptr);
6997 build_decl_var_and_init(ag, subexpr_scope, node, var, err_value, buf_ptr(err_symbol), is_comptime);
6998 err_var_scope = var->child_scope;
6999 } else {
7000 err_var_scope = subexpr_scope;
7001 }
7002 else_expr_result = astgen_node_extra(ag, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base);
7003 if (else_expr_result == ag->codegen->invalid_inst_src)
7004 return else_expr_result;
7005 } else {
7006 else_expr_result = ir_build_const_void(ag, scope, node);
7007 ir_build_end_expr(ag, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
7008 }
7009 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
7010 if (!instr_is_unreachable(else_expr_result))
7011 ir_build_br(ag, scope, node, endif_block, is_comptime);
7012
7013 ir_set_cursor_at_end_and_append_block(ag, endif_block);
7014 Stage1ZirInst **incoming_values = heap::c_allocator.allocate<Stage1ZirInst *>(2);
7015 incoming_values[0] = then_expr_result;
7016 incoming_values[1] = else_expr_result;
7017 Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2);
7018 incoming_blocks[0] = after_then_block;
7019 incoming_blocks[1] = after_else_block;
7020
7021 Stage1ZirInst *phi = ir_build_phi(ag, scope, node, false, 2, incoming_blocks, incoming_values, peer_parent);
7022 return ir_expr_wrap(ag, scope, phi, result_loc);
7023}
7024
7025static bool astgen_switch_prong_expr(Stage1AstGen *ag, Scope *scope, AstNode *switch_node, AstNode *prong_node,
7026 Stage1ZirBasicBlock *end_block, Stage1ZirInst *is_comptime, Stage1ZirInst *var_is_comptime,
7027 Stage1ZirInst *target_value_ptr, Stage1ZirInst **prong_values, size_t prong_values_len,
7028 ZigList<Stage1ZirBasicBlock *> *incoming_blocks, ZigList<Stage1ZirInst *> *incoming_values,
7029 Stage1ZirInstSwitchElseVar **out_switch_else_var, LVal lval, ResultLoc *result_loc)
7030{
7031 assert(switch_node->type == NodeTypeSwitchExpr);
7032 assert(prong_node->type == NodeTypeSwitchProng);
7033
7034 if (prong_node->data.switch_prong.is_inline) {
7035 exec_add_error_node(ag->codegen, ag->exec, prong_node,
7036 buf_sprintf("inline switch cases not supported by stage1"));
7037 return ag->codegen->invalid_inst_src;
7038 }
7039
7040 AstNode *expr_node = prong_node->data.switch_prong.expr;
7041 AstNode *var_symbol_node = prong_node->data.switch_prong.var_symbol;
7042 Scope *child_scope;
7043 if (var_symbol_node) {
7044 assert(var_symbol_node->type == NodeTypeIdentifier);
7045 Buf *var_name = node_identifier_buf(var_symbol_node);
7046 bool var_is_ptr = prong_node->data.switch_prong.var_is_ptr;
7047
7048 bool is_shadowable = false;
7049 bool is_const = true;
7050 ZigVar *var = ir_create_var(ag, var_symbol_node, scope,
7051 var_name, is_const, is_const, is_shadowable, var_is_comptime);
7052 child_scope = var->child_scope;
7053 Stage1ZirInst *var_value;
7054 if (out_switch_else_var != nullptr) {
7055 Stage1ZirInstSwitchElseVar *switch_else_var = ir_build_switch_else_var(ag, scope, var_symbol_node,
7056 target_value_ptr);
7057 *out_switch_else_var = switch_else_var;
7058 Stage1ZirInst *payload_ptr = &switch_else_var->base;
7059 var_value = var_is_ptr ?
7060 payload_ptr : ir_build_load_ptr(ag, scope, var_symbol_node, payload_ptr);
7061 } else if (prong_values != nullptr) {
7062 Stage1ZirInst *payload_ptr = ir_build_switch_var(ag, scope, var_symbol_node, target_value_ptr,
7063 prong_values, prong_values_len);
7064 var_value = var_is_ptr ?
7065 payload_ptr : ir_build_load_ptr(ag, scope, var_symbol_node, payload_ptr);
7066 } else {
7067 var_value = var_is_ptr ?
7068 target_value_ptr : ir_build_load_ptr(ag, scope, var_symbol_node, target_value_ptr);
7069 }
7070 build_decl_var_and_init(ag, scope, var_symbol_node, var, var_value, buf_ptr(var_name), var_is_comptime);
7071 } else {
7072 child_scope = scope;
7073 }
7074
7075 Stage1ZirInst *expr_result = astgen_node_extra(ag, expr_node, child_scope, lval, result_loc);
7076 if (expr_result == ag->codegen->invalid_inst_src)
7077 return false;
7078 if (!instr_is_unreachable(expr_result))
7079 ir_build_br(ag, scope, switch_node, end_block, is_comptime);
7080 incoming_blocks->append(ag->current_basic_block);
7081 incoming_values->append(expr_result);
7082 return true;
7083}
7084
7085static Stage1ZirInst *astgen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval,
7086 ResultLoc *result_loc)
7087{
7088 assert(node->type == NodeTypeSwitchExpr);
7089
7090 AstNode *target_node = node->data.switch_expr.expr;
7091 Stage1ZirInst *target_value_ptr = astgen_node_extra(ag, target_node, scope, LValPtr, nullptr);
7092 if (target_value_ptr == ag->codegen->invalid_inst_src)
7093 return target_value_ptr;
7094 Stage1ZirInst *target_value = ir_build_switch_target(ag, scope, node, target_value_ptr);
7095
7096 Stage1ZirBasicBlock *else_block = ir_create_basic_block(ag, scope, "SwitchElse");
7097 Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, scope, "SwitchEnd");
7098
7099 size_t prong_count = node->data.switch_expr.prongs.length;
7100 ZigList<Stage1ZirInstSwitchBrCase> cases = {0};
7101
7102 Stage1ZirInst *is_comptime;
7103 Stage1ZirInst *var_is_comptime;
7104 if (ir_should_inline(ag->exec, scope)) {
7105 is_comptime = ir_build_const_bool(ag, scope, node, true);
7106 var_is_comptime = is_comptime;
7107 } else {
7108 is_comptime = ir_build_test_comptime(ag, scope, node, target_value);
7109 var_is_comptime = ir_build_test_comptime(ag, scope, node, target_value_ptr);
7110 }
7111
7112 ZigList<Stage1ZirInst *> incoming_values = {0};
7113 ZigList<Stage1ZirBasicBlock *> incoming_blocks = {0};
7114 ZigList<Stage1ZirInstCheckSwitchProngsRange> check_ranges = {0};
7115
7116 Stage1ZirInstSwitchElseVar *switch_else_var = nullptr;
7117
7118 ResultLocPeerParent *peer_parent = heap::c_allocator.create<ResultLocPeerParent>();
7119 peer_parent->base.id = ResultLocIdPeerParent;
7120 peer_parent->base.allow_write_through_const = result_loc->allow_write_through_const;
7121 peer_parent->end_bb = end_block;
7122 peer_parent->is_comptime = is_comptime;
7123 peer_parent->parent = result_loc;
7124
7125 ir_build_reset_result(ag, scope, node, &peer_parent->base);
7126
7127 // First do the else and the ranges
7128 Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime);
7129 Scope *comptime_scope = create_comptime_scope(ag->codegen, node, scope);
7130 AstNode *else_prong = nullptr;
7131 AstNode *underscore_prong = nullptr;
7132 for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) {
7133 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
7134 size_t prong_item_count = prong_node->data.switch_prong.items.length;
7135 if (prong_node->data.switch_prong.any_items_are_range) {
7136 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
7137
7138 Stage1ZirInst *ok_bit = nullptr;
7139 AstNode *last_item_node = nullptr;
7140 for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {
7141 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
7142 last_item_node = item_node;
7143 if (item_node->type == NodeTypeSwitchRange) {
7144 AstNode *start_node = item_node->data.switch_range.start;
7145 AstNode *end_node = item_node->data.switch_range.end;
7146
7147 Stage1ZirInst *start_value = astgen_node(ag, start_node, comptime_scope);
7148 if (start_value == ag->codegen->invalid_inst_src)
7149 return ag->codegen->invalid_inst_src;
7150
7151 Stage1ZirInst *end_value = astgen_node(ag, end_node, comptime_scope);
7152 if (end_value == ag->codegen->invalid_inst_src)
7153 return ag->codegen->invalid_inst_src;
7154
7155 Stage1ZirInstCheckSwitchProngsRange *check_range = check_ranges.add_one();
7156 check_range->start = start_value;
7157 check_range->end = end_value;
7158
7159 Stage1ZirInst *lower_range_ok = ir_build_bin_op(ag, scope, item_node, IrBinOpCmpGreaterOrEq,
7160 target_value, start_value, false);
7161 Stage1ZirInst *upper_range_ok = ir_build_bin_op(ag, scope, item_node, IrBinOpCmpLessOrEq,
7162 target_value, end_value, false);
7163 Stage1ZirInst *both_ok = ir_build_bin_op(ag, scope, item_node, IrBinOpBoolAnd,
7164 lower_range_ok, upper_range_ok, false);
7165 if (ok_bit) {
7166 ok_bit = ir_build_bin_op(ag, scope, item_node, IrBinOpBoolOr, both_ok, ok_bit, false);
7167 } else {
7168 ok_bit = both_ok;
7169 }
7170 } else {
7171 Stage1ZirInst *item_value = astgen_node(ag, item_node, comptime_scope);
7172 if (item_value == ag->codegen->invalid_inst_src)
7173 return ag->codegen->invalid_inst_src;
7174
7175 Stage1ZirInstCheckSwitchProngsRange *check_range = check_ranges.add_one();
7176 check_range->start = item_value;
7177 check_range->end = item_value;
7178
7179 Stage1ZirInst *cmp_ok = ir_build_bin_op(ag, scope, item_node, IrBinOpCmpEq,
7180 item_value, target_value, false);
7181 if (ok_bit) {
7182 ok_bit = ir_build_bin_op(ag, scope, item_node, IrBinOpBoolOr, cmp_ok, ok_bit, false);
7183 } else {
7184 ok_bit = cmp_ok;
7185 }
7186 }
7187 }
7188
7189 Stage1ZirBasicBlock *range_block_yes = ir_create_basic_block(ag, scope, "SwitchRangeYes");
7190 Stage1ZirBasicBlock *range_block_no = ir_create_basic_block(ag, scope, "SwitchRangeNo");
7191
7192 assert(ok_bit);
7193 assert(last_item_node);
7194 Stage1ZirInst *br_inst = ir_build_cond_br(ag, scope, last_item_node, ok_bit,
7195 range_block_yes, range_block_no, is_comptime);
7196 if (peer_parent->base.source_instruction == nullptr) {
7197 peer_parent->base.source_instruction = br_inst;
7198 }
7199
7200 if (peer_parent->peers.length > 0) {
7201 peer_parent->peers.last()->next_bb = range_block_yes;
7202 }
7203 peer_parent->peers.append(this_peer_result_loc);
7204 ir_set_cursor_at_end_and_append_block(ag, range_block_yes);
7205 if (!astgen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block,
7206 is_comptime, var_is_comptime, target_value_ptr, nullptr, 0,
7207 &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base))
7208 {
7209 return ag->codegen->invalid_inst_src;
7210 }
7211
7212 ir_set_cursor_at_end_and_append_block(ag, range_block_no);
7213 } else {
7214 if (prong_item_count == 0) {
7215 if (else_prong) {
7216 ErrorMsg *msg = add_node_error(ag->codegen, prong_node,
7217 buf_sprintf("multiple else prongs in switch expression"));
7218 add_error_note(ag->codegen, msg, else_prong,
7219 buf_sprintf("previous else prong here"));
7220 return ag->codegen->invalid_inst_src;
7221 }
7222 else_prong = prong_node;
7223 } else if (prong_item_count == 1 &&
7224 prong_node->data.switch_prong.items.at(0)->type == NodeTypeIdentifier &&
7225 buf_eql_str(node_identifier_buf(prong_node->data.switch_prong.items.at(0)), "_")) {
7226 if (underscore_prong) {
7227 ErrorMsg *msg = add_node_error(ag->codegen, prong_node,
7228 buf_sprintf("multiple '_' prongs in switch expression"));
7229 add_error_note(ag->codegen, msg, underscore_prong,
7230 buf_sprintf("previous '_' prong here"));
7231 return ag->codegen->invalid_inst_src;
7232 }
7233 underscore_prong = prong_node;
7234 } else {
7235 continue;
7236 }
7237 if (underscore_prong && else_prong) {
7238 ErrorMsg *msg = add_node_error(ag->codegen, prong_node,
7239 buf_sprintf("else and '_' prong in switch expression"));
7240 if (underscore_prong == prong_node)
7241 add_error_note(ag->codegen, msg, else_prong,
7242 buf_sprintf("else prong here"));
7243 else
7244 add_error_note(ag->codegen, msg, underscore_prong,
7245 buf_sprintf("'_' prong here"));
7246 return ag->codegen->invalid_inst_src;
7247 }
7248 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
7249
7250 Stage1ZirBasicBlock *prev_block = ag->current_basic_block;
7251 if (peer_parent->peers.length > 0) {
7252 peer_parent->peers.last()->next_bb = else_block;
7253 }
7254 peer_parent->peers.append(this_peer_result_loc);
7255 ir_set_cursor_at_end_and_append_block(ag, else_block);
7256 if (!astgen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block,
7257 is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values,
7258 &switch_else_var, LValNone, &this_peer_result_loc->base))
7259 {
7260 return ag->codegen->invalid_inst_src;
7261 }
7262 ir_set_cursor_at_end(ag, prev_block);
7263 }
7264 }
7265
7266 // next do the non-else non-ranges
7267 for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) {
7268 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
7269 size_t prong_item_count = prong_node->data.switch_prong.items.length;
7270 if (prong_item_count == 0)
7271 continue;
7272 if (prong_node->data.switch_prong.any_items_are_range)
7273 continue;
7274 if (underscore_prong == prong_node)
7275 continue;
7276
7277 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
7278
7279 Stage1ZirBasicBlock *prong_block = ir_create_basic_block(ag, scope, "SwitchProng");
7280 Stage1ZirInst **items = heap::c_allocator.allocate<Stage1ZirInst *>(prong_item_count);
7281
7282 for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {
7283 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
7284 assert(item_node->type != NodeTypeSwitchRange);
7285
7286 Stage1ZirInst *item_value = astgen_node(ag, item_node, comptime_scope);
7287 if (item_value == ag->codegen->invalid_inst_src)
7288 return ag->codegen->invalid_inst_src;
7289
7290 Stage1ZirInstCheckSwitchProngsRange *check_range = check_ranges.add_one();
7291 check_range->start = item_value;
7292 check_range->end = item_value;
7293
7294 Stage1ZirInstSwitchBrCase *this_case = cases.add_one();
7295 this_case->value = item_value;
7296 this_case->block = prong_block;
7297
7298 items[item_i] = item_value;
7299 }
7300
7301 Stage1ZirBasicBlock *prev_block = ag->current_basic_block;
7302 if (peer_parent->peers.length > 0) {
7303 peer_parent->peers.last()->next_bb = prong_block;
7304 }
7305 peer_parent->peers.append(this_peer_result_loc);
7306 ir_set_cursor_at_end_and_append_block(ag, prong_block);
7307 if (!astgen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block,
7308 is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count,
7309 &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base))
7310 {
7311 return ag->codegen->invalid_inst_src;
7312 }
7313
7314 ir_set_cursor_at_end(ag, prev_block);
7315
7316 }
7317
7318 Stage1ZirInst *switch_prongs_void = ir_build_check_switch_prongs(ag, scope, node, target_value,
7319 check_ranges.items, check_ranges.length, else_prong, underscore_prong != nullptr);
7320
7321 Stage1ZirInst *br_instruction;
7322 if (cases.length == 0) {
7323 br_instruction = ir_build_br(ag, scope, node, else_block, is_comptime);
7324 } else {
7325 Stage1ZirInstSwitchBr *switch_br = ir_build_switch_br_src(ag, scope, node, target_value, else_block,
7326 cases.length, cases.items, is_comptime, switch_prongs_void);
7327 if (switch_else_var != nullptr) {
7328 switch_else_var->switch_br = switch_br;
7329 }
7330 br_instruction = &switch_br->base;
7331 }
7332 if (peer_parent->base.source_instruction == nullptr) {
7333 peer_parent->base.source_instruction = br_instruction;
7334 }
7335 for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
7336 peer_parent->peers.at(i)->base.source_instruction = peer_parent->base.source_instruction;
7337 }
7338
7339 if (!else_prong && !underscore_prong) {
7340 if (peer_parent->peers.length != 0) {
7341 peer_parent->peers.last()->next_bb = else_block;
7342 }
7343 ir_set_cursor_at_end_and_append_block(ag, else_block);
7344 ir_build_unreachable(ag, scope, node);
7345 } else {
7346 if (peer_parent->peers.length != 0) {
7347 peer_parent->peers.last()->next_bb = end_block;
7348 }
7349 }
7350
7351 ir_set_cursor_at_end_and_append_block(ag, end_block);
7352 assert(incoming_blocks.length == incoming_values.length);
7353 Stage1ZirInst *result_instruction;
7354 if (incoming_blocks.length == 0) {
7355 result_instruction = ir_build_const_void(ag, scope, node);
7356 } else {
7357 result_instruction = ir_build_phi(ag, scope, node, false, incoming_blocks.length,
7358 incoming_blocks.items, incoming_values.items, peer_parent);
7359 }
7360 return ir_lval_wrap(ag, scope, result_instruction, lval, result_loc);
7361}
7362
7363static Stage1ZirInst *astgen_comptime(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval) {
7364 assert(node->type == NodeTypeCompTime);
7365
7366 Scope *child_scope = create_comptime_scope(ag->codegen, node, parent_scope);
7367 // purposefully pass null for result_loc and let EndExpr handle it
7368 return astgen_node_extra(ag, node->data.comptime_expr.expr, child_scope, lval, nullptr);
7369}
7370
7371static Stage1ZirInst *astgen_nosuspend(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval) {
7372 assert(node->type == NodeTypeNoSuspend);
7373
7374 Scope *child_scope = create_nosuspend_scope(ag->codegen, node, parent_scope);
7375 // purposefully pass null for result_loc and let EndExpr handle it
7376 return astgen_node_extra(ag, node->data.nosuspend_expr.expr, child_scope, lval, nullptr);
7377}
7378
7379static Stage1ZirInst *astgen_return_from_block(Stage1AstGen *ag, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) {
7380 Stage1ZirInst *is_comptime;
7381 if (ir_should_inline(ag->exec, break_scope)) {
7382 is_comptime = ir_build_const_bool(ag, break_scope, node, true);
7383 } else {
7384 is_comptime = block_scope->is_comptime;
7385 }
7386
7387 Stage1ZirInst *result_value;
7388 if (node->data.break_expr.expr) {
7389 ResultLocPeer *peer_result = create_peer_result(block_scope->peer_parent);
7390 block_scope->peer_parent->peers.append(peer_result);
7391
7392 result_value = astgen_node_extra(ag, node->data.break_expr.expr, break_scope, block_scope->lval,
7393 &peer_result->base);
7394 if (result_value == ag->codegen->invalid_inst_src)
7395 return ag->codegen->invalid_inst_src;
7396 } else {
7397 result_value = ir_build_const_void(ag, break_scope, node);
7398 }
7399
7400 Stage1ZirBasicBlock *dest_block = block_scope->end_block;
7401 if (!astgen_defers_for_block(ag, break_scope, dest_block->scope, nullptr, nullptr))
7402 return ag->codegen->invalid_inst_src;
7403
7404 block_scope->incoming_blocks->append(ag->current_basic_block);
7405 block_scope->incoming_values->append(result_value);
7406 return ir_build_br(ag, break_scope, node, dest_block, is_comptime);
7407}
7408
7409static Stage1ZirInst *astgen_break(Stage1AstGen *ag, Scope *break_scope, AstNode *node) {
7410 assert(node->type == NodeTypeBreak);
7411
7412 // Search up the scope. We'll find one of these things first:
7413 // * function definition scope or global scope => error, break outside loop
7414 // * defer expression scope => error, cannot break out of defer expression
7415 // * loop scope => OK
7416 // * (if it's a labeled break) labeled block => OK
7417
7418 Scope *search_scope = break_scope;
7419 ScopeLoop *loop_scope;
7420 for (;;) {
7421 if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) {
7422 if (node->data.break_expr.name != nullptr) {
7423 add_node_error(ag->codegen, node, buf_sprintf("label not found: '%s'", buf_ptr(node->data.break_expr.name)));
7424 return ag->codegen->invalid_inst_src;
7425 } else {
7426 add_node_error(ag->codegen, node, buf_sprintf("break expression outside loop"));
7427 return ag->codegen->invalid_inst_src;
7428 }
7429 } else if (search_scope->id == ScopeIdDeferExpr) {
7430 add_node_error(ag->codegen, node, buf_sprintf("cannot break out of defer expression"));
7431 return ag->codegen->invalid_inst_src;
7432 } else if (search_scope->id == ScopeIdLoop) {
7433 ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope;
7434 if (node->data.break_expr.name == nullptr ||
7435 (this_loop_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_loop_scope->name)))
7436 {
7437 this_loop_scope->name_used = true;
7438 loop_scope = this_loop_scope;
7439 break;
7440 }
7441 } else if (search_scope->id == ScopeIdBlock) {
7442 ScopeBlock *this_block_scope = (ScopeBlock *)search_scope;
7443 if (node->data.break_expr.name != nullptr &&
7444 (this_block_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_block_scope->name)))
7445 {
7446 assert(this_block_scope->end_block != nullptr);
7447 this_block_scope->name_used = true;
7448 return astgen_return_from_block(ag, break_scope, node, this_block_scope);
7449 }
7450 } else if (search_scope->id == ScopeIdSuspend) {
7451 add_node_error(ag->codegen, node, buf_sprintf("cannot break out of suspend block"));
7452 return ag->codegen->invalid_inst_src;
7453 }
7454 search_scope = search_scope->parent;
7455 }
7456
7457 Stage1ZirInst *is_comptime;
7458 if (ir_should_inline(ag->exec, break_scope)) {
7459 is_comptime = ir_build_const_bool(ag, break_scope, node, true);
7460 } else {
7461 is_comptime = loop_scope->is_comptime;
7462 }
7463
7464 Stage1ZirInst *result_value;
7465 if (node->data.break_expr.expr) {
7466 ResultLocPeer *peer_result = create_peer_result(loop_scope->peer_parent);
7467 loop_scope->peer_parent->peers.append(peer_result);
7468
7469 result_value = astgen_node_extra(ag, node->data.break_expr.expr, break_scope,
7470 loop_scope->lval, &peer_result->base);
7471 if (result_value == ag->codegen->invalid_inst_src)
7472 return ag->codegen->invalid_inst_src;
7473 } else {
7474 result_value = ir_build_const_void(ag, break_scope, node);
7475 }
7476
7477 Stage1ZirBasicBlock *dest_block = loop_scope->break_block;
7478 if (!astgen_defers_for_block(ag, break_scope, dest_block->scope, nullptr, nullptr))
7479 return ag->codegen->invalid_inst_src;
7480
7481 loop_scope->incoming_blocks->append(ag->current_basic_block);
7482 loop_scope->incoming_values->append(result_value);
7483 return ir_build_br(ag, break_scope, node, dest_block, is_comptime);
7484}
7485
7486static Stage1ZirInst *astgen_continue(Stage1AstGen *ag, Scope *continue_scope, AstNode *node) {
7487 assert(node->type == NodeTypeContinue);
7488
7489 // Search up the scope. We'll find one of these things first:
7490 // * function definition scope or global scope => error, break outside loop
7491 // * defer expression scope => error, cannot break out of defer expression
7492 // * loop scope => OK
7493
7494 ZigList<ScopeRuntime *> runtime_scopes = {};
7495
7496 Scope *search_scope = continue_scope;
7497 ScopeLoop *loop_scope;
7498 for (;;) {
7499 if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) {
7500 if (node->data.continue_expr.name != nullptr) {
7501 add_node_error(ag->codegen, node, buf_sprintf("labeled loop not found: '%s'", buf_ptr(node->data.continue_expr.name)));
7502 return ag->codegen->invalid_inst_src;
7503 } else {
7504 add_node_error(ag->codegen, node, buf_sprintf("continue expression outside loop"));
7505 return ag->codegen->invalid_inst_src;
7506 }
7507 } else if (search_scope->id == ScopeIdDeferExpr) {
7508 add_node_error(ag->codegen, node, buf_sprintf("cannot continue out of defer expression"));
7509 return ag->codegen->invalid_inst_src;
7510 } else if (search_scope->id == ScopeIdLoop) {
7511 ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope;
7512 if (node->data.continue_expr.name == nullptr ||
7513 (this_loop_scope->name != nullptr && buf_eql_buf(node->data.continue_expr.name, this_loop_scope->name)))
7514 {
7515 this_loop_scope->name_used = true;
7516 loop_scope = this_loop_scope;
7517 break;
7518 }
7519 } else if (search_scope->id == ScopeIdRuntime) {
7520 ScopeRuntime *scope_runtime = (ScopeRuntime *)search_scope;
7521 runtime_scopes.append(scope_runtime);
7522 }
7523 search_scope = search_scope->parent;
7524 }
7525
7526 Stage1ZirInst *is_comptime;
7527 if (ir_should_inline(ag->exec, continue_scope)) {
7528 is_comptime = ir_build_const_bool(ag, continue_scope, node, true);
7529 } else {
7530 is_comptime = loop_scope->is_comptime;
7531 }
7532
7533 for (size_t i = 0; i < runtime_scopes.length; i += 1) {
7534 ScopeRuntime *scope_runtime = runtime_scopes.at(i);
7535 ir_build_check_runtime_scope(ag, continue_scope, node, scope_runtime->is_comptime, is_comptime);
7536 }
7537 runtime_scopes.deinit();
7538
7539 Stage1ZirBasicBlock *dest_block = loop_scope->continue_block;
7540 if (!astgen_defers_for_block(ag, continue_scope, dest_block->scope, nullptr, nullptr))
7541 return ag->codegen->invalid_inst_src;
7542 return ir_build_br(ag, continue_scope, node, dest_block, is_comptime);
7543}
7544
7545static Stage1ZirInst *astgen_error_type(Stage1AstGen *ag, Scope *scope, AstNode *node) {
7546 assert(node->type == NodeTypeErrorType);
7547 return ir_build_const_type(ag, scope, node, ag->codegen->builtin_types.entry_global_error_set);
7548}
7549
7550static Stage1ZirInst *astgen_defer(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) {
7551 assert(node->type == NodeTypeDefer);
7552
7553 ScopeDefer *defer_child_scope = create_defer_scope(ag->codegen, node, parent_scope);
7554 node->data.defer.child_scope = &defer_child_scope->base;
7555
7556 ScopeDeferExpr *defer_expr_scope = create_defer_expr_scope(ag->codegen, node, parent_scope);
7557 node->data.defer.expr_scope = &defer_expr_scope->base;
7558
7559 return ir_build_const_void(ag, parent_scope, node);
7560}
7561
7562static Stage1ZirInst *astgen_slice(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
7563 assert(node->type == NodeTypeSliceExpr);
7564
7565 AstNodeSliceExpr *slice_expr = &node->data.slice_expr;
7566 AstNode *array_node = slice_expr->array_ref_expr;
7567 AstNode *start_node = slice_expr->start;
7568 AstNode *end_node = slice_expr->end;
7569 AstNode *sentinel_node = slice_expr->sentinel;
7570
7571 Stage1ZirInst *ptr_value = astgen_node_extra(ag, array_node, scope, LValPtr, nullptr);
7572 if (ptr_value == ag->codegen->invalid_inst_src)
7573 return ag->codegen->invalid_inst_src;
7574
7575 Stage1ZirInst *start_value = astgen_node(ag, start_node, scope);
7576 if (start_value == ag->codegen->invalid_inst_src)
7577 return ag->codegen->invalid_inst_src;
7578
7579 Stage1ZirInst *end_value;
7580 if (end_node) {
7581 end_value = astgen_node(ag, end_node, scope);
7582 if (end_value == ag->codegen->invalid_inst_src)
7583 return ag->codegen->invalid_inst_src;
7584 } else {
7585 end_value = nullptr;
7586 }
7587
7588 Stage1ZirInst *sentinel_value;
7589 if (sentinel_node) {
7590 sentinel_value = astgen_node(ag, sentinel_node, scope);
7591 if (sentinel_value == ag->codegen->invalid_inst_src)
7592 return ag->codegen->invalid_inst_src;
7593 } else {
7594 sentinel_value = nullptr;
7595 }
7596
7597 Stage1ZirInst *slice = ir_build_slice_src(ag, scope, node, ptr_value, start_value, end_value,
7598 sentinel_value, true, result_loc);
7599 return ir_lval_wrap(ag, scope, slice, lval, result_loc);
7600}
7601
7602static Stage1ZirInst *astgen_catch(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval,
7603 ResultLoc *result_loc)
7604{
7605 assert(node->type == NodeTypeCatchExpr);
7606
7607 AstNode *op1_node = node->data.unwrap_err_expr.op1;
7608 AstNode *op2_node = node->data.unwrap_err_expr.op2;
7609 AstNode *var_node = node->data.unwrap_err_expr.symbol;
7610
7611 if (op2_node->type == NodeTypeUnreachable) {
7612 if (var_node != nullptr) {
7613 assert(var_node->type == NodeTypeIdentifier);
7614 Buf *var_name = node_identifier_buf(var_node);
7615 add_node_error(ag->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
7616 return ag->codegen->invalid_inst_src;
7617 }
7618 return astgen_catch_unreachable(ag, parent_scope, node, op1_node, lval, result_loc);
7619 }
7620
7621
7622 ScopeExpr *spill_scope = create_expr_scope(ag->codegen, op1_node, parent_scope);
7623 spill_scope->spill_harder = true;
7624
7625 Stage1ZirInst *err_union_ptr = astgen_node_extra(ag, op1_node, &spill_scope->base, LValPtr, nullptr);
7626 if (err_union_ptr == ag->codegen->invalid_inst_src)
7627 return ag->codegen->invalid_inst_src;
7628
7629 Stage1ZirInst *is_err = ir_build_test_err_src(ag, parent_scope, node, err_union_ptr, true, false);
7630
7631 Stage1ZirInst *is_comptime;
7632 if (ir_should_inline(ag->exec, parent_scope)) {
7633 is_comptime = ir_build_const_bool(ag, parent_scope, node, true);
7634 } else {
7635 is_comptime = ir_build_test_comptime(ag, parent_scope, node, is_err);
7636 }
7637
7638 Stage1ZirBasicBlock *ok_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrOk");
7639 Stage1ZirBasicBlock *err_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrError");
7640 Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrEnd");
7641 Stage1ZirInst *cond_br_inst = ir_build_cond_br(ag, parent_scope, node, is_err, err_block, ok_block, is_comptime);
7642
7643 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, ok_block, end_block, result_loc,
7644 is_comptime);
7645
7646 ir_set_cursor_at_end_and_append_block(ag, err_block);
7647 Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, &spill_scope->base, is_comptime);
7648 Scope *err_scope;
7649 if (var_node) {
7650 assert(var_node->type == NodeTypeIdentifier);
7651 Buf *var_name = node_identifier_buf(var_node);
7652 bool is_const = true;
7653 bool is_shadowable = false;
7654 ZigVar *var = ir_create_var(ag, node, subexpr_scope, var_name,
7655 is_const, is_const, is_shadowable, is_comptime);
7656 err_scope = var->child_scope;
7657 Stage1ZirInst *err_ptr = ir_build_unwrap_err_code_src(ag, err_scope, node, err_union_ptr);
7658 Stage1ZirInst *err_value = ir_build_load_ptr(ag, err_scope, var_node, err_ptr);
7659 build_decl_var_and_init(ag, err_scope, var_node, var, err_value, buf_ptr(var_name), is_comptime);
7660 } else {
7661 err_scope = subexpr_scope;
7662 }
7663 Stage1ZirInst *err_result = astgen_node_extra(ag, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base);
7664 if (err_result == ag->codegen->invalid_inst_src)
7665 return ag->codegen->invalid_inst_src;
7666 Stage1ZirBasicBlock *after_err_block = ag->current_basic_block;
7667 if (!instr_is_unreachable(err_result))
7668 ir_build_br(ag, parent_scope, node, end_block, is_comptime);
7669
7670 ir_set_cursor_at_end_and_append_block(ag, ok_block);
7671 Stage1ZirInst *unwrapped_ptr = ir_build_unwrap_err_payload_src(ag, parent_scope, node, err_union_ptr, false, false);
7672 Stage1ZirInst *unwrapped_payload = ir_build_load_ptr(ag, parent_scope, node, unwrapped_ptr);
7673 ir_build_end_expr(ag, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base);
7674 Stage1ZirBasicBlock *after_ok_block = ag->current_basic_block;
7675 ir_build_br(ag, parent_scope, node, end_block, is_comptime);
7676
7677 ir_set_cursor_at_end_and_append_block(ag, end_block);
7678 Stage1ZirInst **incoming_values = heap::c_allocator.allocate<Stage1ZirInst *>(2);
7679 incoming_values[0] = err_result;
7680 incoming_values[1] = unwrapped_payload;
7681 Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2);
7682 incoming_blocks[0] = after_err_block;
7683 incoming_blocks[1] = after_ok_block;
7684 Stage1ZirInst *phi = ir_build_phi(ag, parent_scope, node, false, 2, incoming_blocks, incoming_values, peer_parent);
7685 return ir_lval_wrap(ag, parent_scope, phi, lval, result_loc);
7686}
7687
7688static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *outer_scope, Scope *inner_scope) {
7689 if (inner_scope == nullptr || inner_scope == outer_scope) return false;
7690 bool need_comma = render_instance_name_recursive(codegen, name, outer_scope, inner_scope->parent);
7691 if (inner_scope->id != ScopeIdVarDecl)
7692 return need_comma;
7693
7694 ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope;
7695 if (need_comma)
7696 buf_append_char(name, ',');
7697 // TODO: const ptr reinterpret here to make the var type agree with the value?
7698 render_const_value(codegen, name, var_scope->var->const_value);
7699 return true;
7700}
7701
7702Buf *get_anon_type_name(CodeGen *codegen, Stage1Zir *exec, const char *kind_name,
7703 Scope *scope, AstNode *source_node, Buf *out_bare_name, ResultLoc *result_loc)
7704{
7705 // See https://ziglang.org/documentation/master/#Struct-Naming .
7706 bool force_generic = false;
7707 if (result_loc != nullptr
7708 && result_loc->source_instruction != nullptr
7709 && result_loc->source_instruction->source_node != nullptr
7710 ) {
7711 switch (result_loc->source_instruction->source_node->type) {
7712 case NodeTypeVariableDeclaration: {
7713 ZigType *import = get_scope_import(scope);
7714 Buf *name = buf_alloc();
7715 append_namespace_qualification(codegen, name, import);
7716 const auto &basename = result_loc->source_instruction->source_node->data.variable_declaration.symbol;
7717 buf_append_buf(name, basename);
7718 buf_init_from_buf(out_bare_name, basename);
7719 return name;
7720 }
7721 case NodeTypeFnCallExpr:
7722 case NodeTypeStructValueField:
7723 force_generic = true;
7724 break;
7725 default:
7726 break;
7727 }
7728 }
7729
7730 if (!force_generic) {
7731 if (exec != nullptr && exec->name != nullptr) {
7732 buf_resize(out_bare_name, 0);
7733 if (scope->id == ScopeIdDecls) {
7734 ScopeDecls *decls_scope = reinterpret_cast<ScopeDecls *>(scope);
7735 append_namespace_qualification(codegen, out_bare_name, decls_scope->container_type);
7736 }
7737 buf_append_buf(out_bare_name, exec->name);
7738 Buf *namespace_name = buf_alloc();
7739 buf_append_buf(namespace_name, out_bare_name);
7740 return namespace_name;
7741 }
7742 if (exec != nullptr && exec->name_fn != nullptr) {
7743 Buf *name = buf_alloc();
7744 buf_append_buf(name, &exec->name_fn->symbol_name);
7745 buf_appendf(name, "(");
7746 render_instance_name_recursive(codegen, name, &exec->name_fn->fndef_scope->base, exec->begin_scope);
7747 buf_appendf(name, ")");
7748 buf_init_from_buf(out_bare_name, name);
7749 return name;
7750 }
7751 }
7752
7753 ZigType *import = get_scope_import(scope);
7754 Buf *namespace_name = buf_alloc();
7755 append_namespace_qualification(codegen, namespace_name, import);
7756 RootStruct *root_struct = source_node->owner->data.structure.root_struct;
7757 TokenLoc tok_loc = root_struct->token_locs[source_node->main_token];
7758 buf_appendf(namespace_name, "%s:%u:%u", kind_name,
7759 tok_loc.line + 1, tok_loc.column + 1);
7760 buf_init_from_buf(out_bare_name, namespace_name);
7761 return namespace_name;
7762}
7763
7764static Stage1ZirInst *astgen_container_decl(Stage1AstGen *ag, Scope *parent_scope,
7765 AstNode *node, ResultLoc *result_loc)
7766{
7767 assert(node->type == NodeTypeContainerDecl);
7768
7769 ContainerKind kind = node->data.container_decl.kind;
7770 Buf *bare_name = buf_alloc();
7771 Buf *name = get_anon_type_name(ag->codegen,
7772 ag->exec, container_string(kind), parent_scope, node, bare_name, result_loc);
7773
7774 ContainerLayout layout = node->data.container_decl.layout;
7775 ZigType *container_type = get_partial_container_type(ag->codegen, parent_scope,
7776 kind, node, buf_ptr(name), bare_name, layout);
7777 ScopeDecls *child_scope = get_container_scope(container_type);
7778
7779 for (size_t i = 0; i < node->data.container_decl.decls.length; i += 1) {
7780 AstNode *child_node = node->data.container_decl.decls.at(i);
7781 scan_decls(ag->codegen, child_scope, child_node);
7782 }
7783
7784 TldContainer *tld_container = heap::c_allocator.create<TldContainer>();
7785 init_tld(&tld_container->base, TldIdContainer, bare_name, VisibModPub, node, parent_scope);
7786 tld_container->type_entry = container_type;
7787 tld_container->decls_scope = child_scope;
7788 ag->codegen->resolve_queue.append(&tld_container->base);
7789
7790 // Add this to the list to mark as invalid if analyzing this exec fails.
7791 ag->exec->tld_list.append(&tld_container->base);
7792
7793 return ir_build_const_type(ag, parent_scope, node, container_type);
7794}
7795
7796static Stage1ZirInst *astgen_err_set_decl(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) {
7797 assert(node->type == NodeTypeErrorSetDecl);
7798
7799 uint32_t err_count = node->data.err_set_decl.decls.length;
7800
7801 Buf bare_name = BUF_INIT;
7802 Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", parent_scope, node, &bare_name, nullptr);
7803 ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
7804 buf_init_from_buf(&err_set_type->name, type_name);
7805 err_set_type->data.error_set.err_count = err_count;
7806 err_set_type->size_in_bits = ag->codegen->builtin_types.entry_global_error_set->size_in_bits;
7807 err_set_type->abi_align = ag->codegen->builtin_types.entry_global_error_set->abi_align;
7808 err_set_type->abi_size = ag->codegen->builtin_types.entry_global_error_set->abi_size;
7809 err_set_type->data.error_set.errors = heap::c_allocator.allocate<ErrorTableEntry *>(err_count);
7810
7811 size_t errors_count = ag->codegen->errors_by_index.length + err_count;
7812 ErrorTableEntry **errors = heap::c_allocator.allocate<ErrorTableEntry *>(errors_count);
7813
7814 for (uint32_t i = 0; i < err_count; i += 1) {
7815 AstNode *field_node = node->data.err_set_decl.decls.at(i);
7816 AstNode *symbol_node = ast_field_to_symbol_node(field_node);
7817 Buf *err_name = node_identifier_buf(symbol_node);
7818 ErrorTableEntry *err = heap::c_allocator.create<ErrorTableEntry>();
7819 err->decl_node = field_node;
7820 buf_init_from_buf(&err->name, err_name);
7821
7822 auto existing_entry = ag->codegen->error_table.put_unique(err_name, err);
7823 if (existing_entry) {
7824 err->value = existing_entry->value->value;
7825 } else {
7826 size_t error_value_count = ag->codegen->errors_by_index.length;
7827 assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)ag->codegen->err_tag_type->data.integral.bit_count));
7828 err->value = error_value_count;
7829 ag->codegen->errors_by_index.append(err);
7830 }
7831 err_set_type->data.error_set.errors[i] = err;
7832
7833 ErrorTableEntry *prev_err = errors[err->value];
7834 if (prev_err != nullptr) {
7835 ErrorMsg *msg = add_node_error(ag->codegen, ast_field_to_symbol_node(err->decl_node),
7836 buf_sprintf("duplicate error: '%s'", buf_ptr(&err->name)));
7837 add_error_note(ag->codegen, msg, ast_field_to_symbol_node(prev_err->decl_node),
7838 buf_sprintf("other error here"));
7839 return ag->codegen->invalid_inst_src;
7840 }
7841 errors[err->value] = err;
7842 }
7843 heap::c_allocator.deallocate(errors, errors_count);
7844 return ir_build_const_type(ag, parent_scope, node, err_set_type);
7845}
7846
7847static Stage1ZirInst *astgen_fn_proto(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) {
7848 assert(node->type == NodeTypeFnProto);
7849
7850 size_t param_count = node->data.fn_proto.params.length;
7851 Stage1ZirInst **param_types = heap::c_allocator.allocate<Stage1ZirInst*>(param_count);
7852
7853 bool is_var_args = false;
7854 for (size_t i = 0; i < param_count; i += 1) {
7855 AstNode *param_node = node->data.fn_proto.params.at(i);
7856 if (param_node->data.param_decl.is_var_args) {
7857 is_var_args = true;
7858 break;
7859 }
7860 if (param_node->data.param_decl.anytype_token == 0) {
7861 AstNode *type_node = param_node->data.param_decl.type;
7862 Stage1ZirInst *type_value = astgen_node(ag, type_node, parent_scope);
7863 if (type_value == ag->codegen->invalid_inst_src)
7864 return ag->codegen->invalid_inst_src;
7865 param_types[i] = type_value;
7866 } else {
7867 param_types[i] = nullptr;
7868 }
7869 }
7870
7871 Stage1ZirInst *align_value = nullptr;
7872 if (node->data.fn_proto.align_expr != nullptr) {
7873 align_value = astgen_node(ag, node->data.fn_proto.align_expr, parent_scope);
7874 if (align_value == ag->codegen->invalid_inst_src)
7875 return ag->codegen->invalid_inst_src;
7876 }
7877
7878 Stage1ZirInst *callconv_value = nullptr;
7879 if (node->data.fn_proto.callconv_expr != nullptr) {
7880 callconv_value = astgen_node(ag, node->data.fn_proto.callconv_expr, parent_scope);
7881 if (callconv_value == ag->codegen->invalid_inst_src)
7882 return ag->codegen->invalid_inst_src;
7883 }
7884
7885 Stage1ZirInst *return_type;
7886 if (node->data.fn_proto.return_type == nullptr) {
7887 return_type = ir_build_const_type(ag, parent_scope, node, ag->codegen->builtin_types.entry_void);
7888 } else {
7889 return_type = astgen_node(ag, node->data.fn_proto.return_type, parent_scope);
7890 if (return_type == ag->codegen->invalid_inst_src)
7891 return ag->codegen->invalid_inst_src;
7892 }
7893
7894 return ir_build_fn_proto(ag, parent_scope, node, param_types, align_value, callconv_value, return_type, is_var_args);
7895}
7896
7897static Stage1ZirInst *astgen_resume(Stage1AstGen *ag, Scope *scope, AstNode *node) {
7898 assert(node->type == NodeTypeResume);
7899
7900 Stage1ZirInst *target_inst = astgen_node_extra(ag, node->data.resume_expr.expr, scope, LValPtr, nullptr);
7901 if (target_inst == ag->codegen->invalid_inst_src)
7902 return ag->codegen->invalid_inst_src;
7903
7904 return ir_build_resume_src(ag, scope, node, target_inst);
7905}
7906
7907static Stage1ZirInst *astgen_await_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval,
7908 ResultLoc *result_loc)
7909{
7910 assert(node->type == NodeTypeAwaitExpr);
7911
7912 bool is_nosuspend = get_scope_nosuspend(scope) != nullptr;
7913
7914 AstNode *expr_node = node->data.await_expr.expr;
7915 if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) {
7916 AstNode *fn_ref_expr = expr_node->data.fn_call_expr.fn_ref_expr;
7917 Buf *name = node_identifier_buf(fn_ref_expr);
7918 auto entry = ag->codegen->builtin_fn_table.maybe_get(name);
7919 if (entry != nullptr) {
7920 BuiltinFnEntry *builtin_fn = entry->value;
7921 if (builtin_fn->id == BuiltinFnIdAsyncCall) {
7922 return astgen_async_call(ag, scope, node, expr_node, lval, result_loc);
7923 }
7924 }
7925 }
7926
7927 if (!ag->fn) {
7928 add_node_error(ag->codegen, node, buf_sprintf("await outside function definition"));
7929 return ag->codegen->invalid_inst_src;
7930 }
7931 ScopeSuspend *existing_suspend_scope = get_scope_suspend(scope);
7932 if (existing_suspend_scope) {
7933 if (!existing_suspend_scope->reported_err) {
7934 ErrorMsg *msg = add_node_error(ag->codegen, node, buf_sprintf("cannot await inside suspend block"));
7935 add_error_note(ag->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("suspend block here"));
7936 existing_suspend_scope->reported_err = true;
7937 }
7938 return ag->codegen->invalid_inst_src;
7939 }
7940
7941 Stage1ZirInst *target_inst = astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr);
7942 if (target_inst == ag->codegen->invalid_inst_src)
7943 return ag->codegen->invalid_inst_src;
7944
7945 Stage1ZirInst *await_inst = ir_build_await_src(ag, scope, node, target_inst, result_loc, is_nosuspend);
7946 return ir_lval_wrap(ag, scope, await_inst, lval, result_loc);
7947}
7948
7949static Stage1ZirInst *astgen_suspend(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) {
7950 assert(node->type == NodeTypeSuspend);
7951
7952 if (!ag->fn) {
7953 add_node_error(ag->codegen, node, buf_sprintf("suspend outside function definition"));
7954 return ag->codegen->invalid_inst_src;
7955 }
7956 if (get_scope_nosuspend(parent_scope) != nullptr) {
7957 add_node_error(ag->codegen, node, buf_sprintf("suspend in nosuspend scope"));
7958 return ag->codegen->invalid_inst_src;
7959 }
7960
7961 ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope);
7962 if (existing_suspend_scope) {
7963 if (!existing_suspend_scope->reported_err) {
7964 ErrorMsg *msg = add_node_error(ag->codegen, node, buf_sprintf("cannot suspend inside suspend block"));
7965 add_error_note(ag->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("other suspend block here"));
7966 existing_suspend_scope->reported_err = true;
7967 }
7968 return ag->codegen->invalid_inst_src;
7969 }
7970
7971 Stage1ZirInstSuspendBegin *begin = ir_build_suspend_begin_src(ag, parent_scope, node);
7972 ScopeSuspend *suspend_scope = create_suspend_scope(ag->codegen, node, parent_scope);
7973 Scope *child_scope = &suspend_scope->base;
7974 Stage1ZirInst *susp_res = astgen_node(ag, node->data.suspend.block, child_scope);
7975 if (susp_res == ag->codegen->invalid_inst_src)
7976 return ag->codegen->invalid_inst_src;
7977 ir_build_check_statement_is_void(ag, child_scope, node->data.suspend.block, susp_res);
7978
7979 return ir_build_suspend_finish_src(ag, parent_scope, node, begin);
7980}
7981
7982static Stage1ZirInst *astgen_node_raw(Stage1AstGen *ag, AstNode *node, Scope *scope,
7983 LVal lval, ResultLoc *result_loc)
7984{
7985 assert(scope);
7986 switch (node->type) {
7987 case NodeTypeStructValueField:
7988 case NodeTypeParamDecl:
7989 case NodeTypeUsingNamespace:
7990 case NodeTypeSwitchProng:
7991 case NodeTypeSwitchRange:
7992 case NodeTypeStructField:
7993 case NodeTypeErrorSetField:
7994 case NodeTypeFnDef:
7995 case NodeTypeTestDecl:
7996 zig_unreachable();
7997 case NodeTypeBlock:
7998 return astgen_block(ag, scope, node, lval, result_loc);
7999 case NodeTypeGroupedExpr:
8000 return astgen_node_raw(ag, node->data.grouped_expr, scope, lval, result_loc);
8001 case NodeTypeBinOpExpr:
8002 return astgen_bin_op(ag, scope, node, lval, result_loc);
8003 case NodeTypeIntLiteral:
8004 return ir_lval_wrap(ag, scope, astgen_int_lit(ag, scope, node), lval, result_loc);
8005 case NodeTypeFloatLiteral:
8006 return ir_lval_wrap(ag, scope, astgen_float_lit(ag, scope, node), lval, result_loc);
8007 case NodeTypeCharLiteral:
8008 return ir_lval_wrap(ag, scope, astgen_char_lit(ag, scope, node), lval, result_loc);
8009 case NodeTypeIdentifier:
8010 return astgen_identifier(ag, scope, node, lval, result_loc);
8011 case NodeTypeFnCallExpr:
8012 return astgen_fn_call(ag, scope, node, lval, result_loc);
8013 case NodeTypeIfBoolExpr:
8014 return astgen_if_bool_expr(ag, scope, node, lval, result_loc);
8015 case NodeTypePrefixOpExpr:
8016 return astgen_prefix_op_expr(ag, scope, node, lval, result_loc);
8017 case NodeTypeContainerInitExpr:
8018 return astgen_container_init_expr(ag, scope, node, lval, result_loc);
8019 case NodeTypeVariableDeclaration:
8020 return astgen_var_decl(ag, scope, node);
8021 case NodeTypeWhileExpr:
8022 return astgen_while_expr(ag, scope, node, lval, result_loc);
8023 case NodeTypeForExpr:
8024 return astgen_for_expr(ag, scope, node, lval, result_loc);
8025 case NodeTypeArrayAccessExpr:
8026 return astgen_array_access(ag, scope, node, lval, result_loc);
8027 case NodeTypeReturnExpr:
8028 return astgen_return(ag, scope, node, lval, result_loc);
8029 case NodeTypeFieldAccessExpr:
8030 {
8031 Stage1ZirInst *ptr_instruction = astgen_field_access(ag, scope, node);
8032 if (ptr_instruction == ag->codegen->invalid_inst_src)
8033 return ptr_instruction;
8034 if (lval == LValPtr || lval == LValAssign)
8035 return ptr_instruction;
8036
8037 Stage1ZirInst *load_ptr = ir_build_load_ptr(ag, scope, node, ptr_instruction);
8038 return ir_expr_wrap(ag, scope, load_ptr, result_loc);
8039 }
8040 case NodeTypePtrDeref: {
8041 AstNode *expr_node = node->data.ptr_deref_expr.target;
8042
8043 LVal child_lval = lval;
8044 if (child_lval == LValAssign)
8045 child_lval = LValPtr;
8046
8047 Stage1ZirInst *value = astgen_node_extra(ag, expr_node, scope, child_lval, nullptr);
8048 if (value == ag->codegen->invalid_inst_src)
8049 return value;
8050
8051 // We essentially just converted any lvalue from &(x.*) to (&x).*;
8052 // this inhibits checking that x is a pointer later, so we directly
8053 // record whether the pointer check is needed
8054 Stage1ZirInst *un_op = ir_build_un_op_lval(ag, scope, node, IrUnOpDereference, value, lval, result_loc);
8055 return ir_expr_wrap(ag, scope, un_op, result_loc);
8056 }
8057 case NodeTypeUnwrapOptional: {
8058 AstNode *expr_node = node->data.unwrap_optional.expr;
8059
8060 Stage1ZirInst *maybe_ptr = astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr);
8061 if (maybe_ptr == ag->codegen->invalid_inst_src)
8062 return ag->codegen->invalid_inst_src;
8063
8064 Stage1ZirInst *unwrapped_ptr = ir_build_optional_unwrap_ptr(ag, scope, node, maybe_ptr, true );
8065 if (lval == LValPtr || lval == LValAssign)
8066 return unwrapped_ptr;
8067
8068 Stage1ZirInst *load_ptr = ir_build_load_ptr(ag, scope, node, unwrapped_ptr);
8069 return ir_expr_wrap(ag, scope, load_ptr, result_loc);
8070 }
8071 case NodeTypeArrayType:
8072 return ir_lval_wrap(ag, scope, astgen_array_type(ag, scope, node), lval, result_loc);
8073 case NodeTypePointerType:
8074 return ir_lval_wrap(ag, scope, astgen_pointer_type(ag, scope, node), lval, result_loc);
8075 case NodeTypeAnyFrameType:
8076 return ir_lval_wrap(ag, scope, astgen_anyframe_type(ag, scope, node), lval, result_loc);
8077 case NodeTypeStringLiteral:
8078 return ir_lval_wrap(ag, scope, astgen_string_literal(ag, scope, node), lval, result_loc);
8079 case NodeTypeAsmExpr:
8080 return ir_lval_wrap(ag, scope, astgen_asm_expr(ag, scope, node), lval, result_loc);
8081 case NodeTypeIfErrorExpr:
8082 return astgen_if_err_expr(ag, scope, node, lval, result_loc);
8083 case NodeTypeIfOptional:
8084 return astgen_if_optional_expr(ag, scope, node, lval, result_loc);
8085 case NodeTypeSwitchExpr:
8086 return astgen_switch_expr(ag, scope, node, lval, result_loc);
8087 case NodeTypeCompTime:
8088 return ir_expr_wrap(ag, scope, astgen_comptime(ag, scope, node, lval), result_loc);
8089 case NodeTypeNoSuspend:
8090 return ir_expr_wrap(ag, scope, astgen_nosuspend(ag, scope, node, lval), result_loc);
8091 case NodeTypeErrorType:
8092 return ir_lval_wrap(ag, scope, astgen_error_type(ag, scope, node), lval, result_loc);
8093 case NodeTypeBreak:
8094 return ir_lval_wrap(ag, scope, astgen_break(ag, scope, node), lval, result_loc);
8095 case NodeTypeContinue:
8096 return ir_lval_wrap(ag, scope, astgen_continue(ag, scope, node), lval, result_loc);
8097 case NodeTypeUnreachable:
8098 return ir_build_unreachable(ag, scope, node);
8099 case NodeTypeDefer:
8100 return ir_lval_wrap(ag, scope, astgen_defer(ag, scope, node), lval, result_loc);
8101 case NodeTypeSliceExpr:
8102 return astgen_slice(ag, scope, node, lval, result_loc);
8103 case NodeTypeCatchExpr:
8104 return astgen_catch(ag, scope, node, lval, result_loc);
8105 case NodeTypeContainerDecl:
8106 return ir_lval_wrap(ag, scope, astgen_container_decl(ag, scope, node, result_loc), lval, result_loc);
8107 case NodeTypeFnProto:
8108 return ir_lval_wrap(ag, scope, astgen_fn_proto(ag, scope, node), lval, result_loc);
8109 case NodeTypeErrorSetDecl:
8110 return ir_lval_wrap(ag, scope, astgen_err_set_decl(ag, scope, node), lval, result_loc);
8111 case NodeTypeResume:
8112 return ir_lval_wrap(ag, scope, astgen_resume(ag, scope, node), lval, result_loc);
8113 case NodeTypeAwaitExpr:
8114 return astgen_await_expr(ag, scope, node, lval, result_loc);
8115 case NodeTypeSuspend:
8116 return ir_lval_wrap(ag, scope, astgen_suspend(ag, scope, node), lval, result_loc);
8117 case NodeTypeEnumLiteral:
8118 return ir_lval_wrap(ag, scope, astgen_enum_literal(ag, scope, node), lval, result_loc);
8119 case NodeTypeInferredArrayType:
8120 add_node_error(ag->codegen, node,
8121 buf_sprintf("inferred array size invalid here"));
8122 return ag->codegen->invalid_inst_src;
8123 case NodeTypeAnyTypeField:
8124 return ir_lval_wrap(ag, scope,
8125 ir_build_const_type(ag, scope, node, ag->codegen->builtin_types.entry_anytype), lval, result_loc);
8126 }
8127 zig_unreachable();
8128}
8129
8130ResultLoc *no_result_loc(void) {
8131 ResultLocNone *result_loc_none = heap::c_allocator.create<ResultLocNone>();
8132 result_loc_none->base.id = ResultLocIdNone;
8133 return &result_loc_none->base;
8134}
8135
8136static Stage1ZirInst *astgen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scope, LVal lval,
8137 ResultLoc *result_loc)
8138{
8139 if (lval == LValAssign) {
8140 switch (node->type) {
8141 case NodeTypeStructValueField:
8142 case NodeTypeParamDecl:
8143 case NodeTypeUsingNamespace:
8144 case NodeTypeSwitchProng:
8145 case NodeTypeSwitchRange:
8146 case NodeTypeStructField:
8147 case NodeTypeErrorSetField:
8148 case NodeTypeFnDef:
8149 case NodeTypeTestDecl:
8150 zig_unreachable();
8151
8152 // cannot be assigned to
8153 case NodeTypeBlock:
8154 case NodeTypeGroupedExpr:
8155 case NodeTypeBinOpExpr:
8156 case NodeTypeIntLiteral:
8157 case NodeTypeFloatLiteral:
8158 case NodeTypeCharLiteral:
8159 case NodeTypeIfBoolExpr:
8160 case NodeTypeContainerInitExpr:
8161 case NodeTypeVariableDeclaration:
8162 case NodeTypeWhileExpr:
8163 case NodeTypeForExpr:
8164 case NodeTypeReturnExpr:
8165 case NodeTypeArrayType:
8166 case NodeTypePointerType:
8167 case NodeTypeAnyFrameType:
8168 case NodeTypeStringLiteral:
8169 case NodeTypeAsmExpr:
8170 case NodeTypeIfErrorExpr:
8171 case NodeTypeIfOptional:
8172 case NodeTypeSwitchExpr:
8173 case NodeTypeCompTime:
8174 case NodeTypeNoSuspend:
8175 case NodeTypeErrorType:
8176 case NodeTypeBreak:
8177 case NodeTypeContinue:
8178 case NodeTypeUnreachable:
8179 case NodeTypeDefer:
8180 case NodeTypeSliceExpr:
8181 case NodeTypeCatchExpr:
8182 case NodeTypeContainerDecl:
8183 case NodeTypeFnProto:
8184 case NodeTypeErrorSetDecl:
8185 case NodeTypeResume:
8186 case NodeTypeAwaitExpr:
8187 case NodeTypeSuspend:
8188 case NodeTypeEnumLiteral:
8189 case NodeTypeInferredArrayType:
8190 case NodeTypeAnyTypeField:
8191 case NodeTypePrefixOpExpr:
8192 add_node_error(ag->codegen, node,
8193 buf_sprintf("invalid left-hand side to assignment"));
8194 return ag->codegen->invalid_inst_src;
8195
8196 // @field can be assigned to
8197 case NodeTypeFnCallExpr:
8198 if (node->data.fn_call_expr.modifier == CallModifierBuiltin) {
8199 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
8200 Buf *name = node_identifier_buf(fn_ref_expr);
8201 auto entry = ag->codegen->builtin_fn_table.maybe_get(name);
8202
8203 if (!entry) {
8204 add_node_error(ag->codegen, node,
8205 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
8206 return ag->codegen->invalid_inst_src;
8207 }
8208
8209 if (entry->value->id == BuiltinFnIdField) {
8210 break;
8211 }
8212 }
8213 add_node_error(ag->codegen, node,
8214 buf_sprintf("invalid left-hand side to assignment"));
8215 return ag->codegen->invalid_inst_src;
8216
8217
8218 // can be assigned to
8219 case NodeTypeUnwrapOptional:
8220 case NodeTypePtrDeref:
8221 case NodeTypeFieldAccessExpr:
8222 case NodeTypeArrayAccessExpr:
8223 case NodeTypeIdentifier:
8224 break;
8225 }
8226 }
8227 if (result_loc == nullptr) {
8228 // Create a result location indicating there is none - but if one gets created
8229 // it will be properly distributed.
8230 result_loc = no_result_loc();
8231 ir_build_reset_result(ag, scope, node, result_loc);
8232 }
8233 Scope *child_scope;
8234 if (ag->exec->is_inline ||
8235 (ag->fn != nullptr && ag->fn->child_scope == scope))
8236 {
8237 child_scope = scope;
8238 } else {
8239 child_scope = &create_expr_scope(ag->codegen, node, scope)->base;
8240 }
8241 Stage1ZirInst *result = astgen_node_raw(ag, node, child_scope, lval, result_loc);
8242 if (result == ag->codegen->invalid_inst_src) {
8243 if (ag->exec->first_err_trace_msg == nullptr) {
8244 ag->exec->first_err_trace_msg = ag->codegen->trace_err;
8245 }
8246 }
8247 return result;
8248}
8249
8250static Stage1ZirInst *astgen_node(Stage1AstGen *ag, AstNode *node, Scope *scope) {
8251 return astgen_node_extra(ag, node, scope, LValNone, nullptr);
8252}
8253
8254bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *stage1_zir,
8255 ZigFn *fn, bool in_c_import_scope)
8256{
8257 assert(node->owner);
8258
8259 Stage1AstGen ir_builder = {0};
8260 Stage1AstGen *ag = &ir_builder;
8261
8262 ag->codegen = codegen;
8263 ag->fn = fn;
8264 ag->in_c_import_scope = in_c_import_scope;
8265 ag->exec = stage1_zir;
8266 ag->main_block_node = node;
8267
8268 Stage1ZirBasicBlock *entry_block = ir_create_basic_block(ag, scope, "Entry");
8269 ir_set_cursor_at_end_and_append_block(ag, entry_block);
8270 // Entry block gets a reference because we enter it to begin.
8271 ir_ref_bb(ag->current_basic_block);
8272
8273 Stage1ZirInst *result = astgen_node_extra(ag, node, scope, LValNone, nullptr);
8274
8275 if (result == ag->codegen->invalid_inst_src)
8276 return false;
8277
8278 if (ag->exec->first_err_trace_msg != nullptr) {
8279 codegen->trace_err = ag->exec->first_err_trace_msg;
8280 return false;
8281 }
8282
8283 if (!instr_is_unreachable(result)) {
8284 ir_build_add_implicit_return_type(ag, scope, result->source_node, result, nullptr);
8285 // no need for save_err_ret_addr because this cannot return error
8286 ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>();
8287 result_loc_ret->base.id = ResultLocIdReturn;
8288 ir_build_reset_result(ag, scope, node, &result_loc_ret->base);
8289 ir_build_end_expr(ag, scope, node, result, &result_loc_ret->base);
8290 ir_build_return_src(ag, scope, result->source_node, result);
8291 }
8292
8293 return true;
8294}
8295
8296bool stage1_astgen_fn(CodeGen *codegen, ZigFn *fn) {
8297 assert(fn != nullptr);
8298 assert(fn->child_scope != nullptr);
8299 return stage1_astgen(codegen, fn->body_node, fn->child_scope, fn->stage1_zir, fn, false);
8300}
8301
8302void invalidate_exec(Stage1Zir *exec, ErrorMsg *msg) {
8303 if (exec->first_err_trace_msg != nullptr)
8304 return;
8305
8306 exec->first_err_trace_msg = msg;
8307
8308 for (size_t i = 0; i < exec->tld_list.length; i += 1) {
8309 exec->tld_list.items[i]->resolution = TldResolutionInvalid;
8310 }
8311}
8312
8313AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node) {
8314 if (err_set_field_node->type == NodeTypeIdentifier) {
8315 return err_set_field_node;
8316 } else if (err_set_field_node->type == NodeTypeErrorSetField) {
8317 assert(err_set_field_node->data.err_set_field.field_name->type == NodeTypeIdentifier);
8318 return err_set_field_node->data.err_set_field.field_name;
8319 } else {
8320 return err_set_field_node;
8321 }
8322}
8323
8324void ir_add_call_stack_errors_gen(CodeGen *codegen, Stage1Air *exec, ErrorMsg *err_msg, int limit) {
8325 if (!exec || !exec->source_node || limit < 0) return;
8326 add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here"));
8327
8328 ir_add_call_stack_errors_gen(codegen, exec->parent_exec, err_msg, limit - 1);
8329}
8330
8331void Stage1ZirInst::src() {
8332 Stage1ZirInst *inst = this;
8333 if (inst->source_node != nullptr) {
8334 inst->source_node->src();
8335 } else {
8336 fprintf(stderr, "(null source node)\n");
8337 }
8338}
8339
src/stage1/astgen.hpp deleted-37
...@@ -1,37 +0,0 @@
1/*
2 * Copyright (c) 2021 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_ASTGEN_HPP
9#define ZIG_ASTGEN_HPP
10
11#include "all_types.hpp"
12
13bool stage1_astgen(CodeGen *g, AstNode *node, Scope *scope, Stage1Zir *stage1_zir,
14 ZigFn *fn, bool in_c_import_scope);
15bool stage1_astgen_fn(CodeGen *g, ZigFn *fn_entry);
16
17bool ir_inst_src_has_side_effects(Stage1ZirInst *inst);
18
19ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope,
20 Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, Stage1ZirInst *is_comptime,
21 bool skip_name_check);
22
23ResultLoc *no_result_loc(void);
24
25void invalidate_exec(Stage1Zir *exec, ErrorMsg *msg);
26
27AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node);
28void ir_add_call_stack_errors_gen(CodeGen *codegen, Stage1Air *exec, ErrorMsg *err_msg,
29 int limit);
30
31void destroy_instruction_src(Stage1ZirInst *inst);
32
33bool ir_should_inline(Stage1Zir *exec, Scope *scope);
34Buf *get_anon_type_name(CodeGen *codegen, Stage1Zir *exec, const char *kind_name,
35 Scope *scope, AstNode *source_node, Buf *out_bare_name, ResultLoc *result_loc);
36
37#endif
src/stage1/bigfloat.cpp deleted-220
...@@ -1,220 +0,0 @@
1/*
2 * Copyright (c) 2017 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "bigfloat.hpp"
9#include "bigint.hpp"
10#include "buffer.hpp"
11#include "softfloat.hpp"
12#include "softfloat_ext.hpp"
13#include "parse_f128.h"
14#include <stdio.h>
15#include <math.h>
16#include <errno.h>
17
18
19void bigfloat_init_128(BigFloat *dest, float128_t x) {
20 dest->value = x;
21}
22
23void bigfloat_init_16(BigFloat *dest, float16_t x) {
24 f16_to_f128M(x, &dest->value);
25}
26
27void bigfloat_init_32(BigFloat *dest, float x) {
28 float32_t f32_val;
29 memcpy(&f32_val, &x, sizeof(float));
30 f32_to_f128M(f32_val, &dest->value);
31}
32
33void bigfloat_init_64(BigFloat *dest, double x) {
34 float64_t f64_val;
35 memcpy(&f64_val, &x, sizeof(double));
36 f64_to_f128M(f64_val, &dest->value);
37}
38
39void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x) {
40 memcpy(&dest->value, &x->value, sizeof(float128_t));
41}
42
43void bigfloat_init_bigint(BigFloat *dest, const BigInt *op) {
44 ui32_to_f128M(0, &dest->value);
45 if (op->digit_count == 0)
46 return;
47
48 float128_t base;
49 ui64_to_f128M(UINT64_MAX, &base);
50 float128_t one_f128;
51 ui32_to_f128M(1, &one_f128);
52 f128M_add(&base, &one_f128, &base);
53
54 const uint64_t *digits = bigint_ptr(op);
55
56 for (size_t i = op->digit_count - 1;;) {
57 float128_t digit_f128;
58 ui64_to_f128M(digits[i], &digit_f128);
59
60 f128M_mulAdd(&dest->value, &base, &digit_f128, &dest->value);
61
62 if (i == 0) {
63 if (op->is_negative) {
64 f128M_neg(&dest->value, &dest->value);
65 }
66 return;
67 }
68 i -= 1;
69 }
70}
71
72Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr) {
73 char *str_begin = (char *)buf_ptr;
74 char *str_end;
75
76 errno = 0;
77 dest->value = parse_f128(str_begin, &str_end);
78 if (errno) {
79 return ErrorOverflow;
80 }
81
82 return ErrorNone;
83}
84
85void bigfloat_add(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
86 f128M_add(&op1->value, &op2->value, &dest->value);
87}
88
89void bigfloat_negate(BigFloat *dest, const BigFloat *op) {
90 f128M_neg(&op->value, &dest->value);
91}
92
93void bigfloat_sub(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
94 f128M_sub(&op1->value, &op2->value, &dest->value);
95}
96
97void bigfloat_mul(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
98 f128M_mul(&op1->value, &op2->value, &dest->value);
99}
100
101void bigfloat_div(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
102 f128M_div(&op1->value, &op2->value, &dest->value);
103}
104
105void bigfloat_div_trunc(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
106 f128M_div(&op1->value, &op2->value, &dest->value);
107 f128M_roundToInt(&dest->value, softfloat_round_minMag, false, &dest->value);
108}
109
110void bigfloat_div_floor(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
111 f128M_div(&op1->value, &op2->value, &dest->value);
112 f128M_roundToInt(&dest->value, softfloat_round_min, false, &dest->value);
113}
114
115void bigfloat_rem(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
116 f128M_rem(&op1->value, &op2->value, &dest->value);
117}
118
119void bigfloat_mod(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
120 f128M_rem(&op1->value, &op2->value, &dest->value);
121 f128M_add(&dest->value, &op2->value, &dest->value);
122 f128M_rem(&dest->value, &op2->value, &dest->value);
123}
124
125void bigfloat_append_buf(Buf *buf, const BigFloat *op) {
126 const size_t extra_len = 100;
127 size_t old_len = buf_len(buf);
128 buf_resize(buf, old_len + extra_len);
129
130 // TODO actually print f128
131 float64_t f64_value = f128M_to_f64(&op->value);
132 double double_value;
133 memcpy(&double_value, &f64_value, sizeof(double));
134
135 int len = snprintf(buf_ptr(buf) + old_len, extra_len, "%f", double_value);
136 assert(len > 0);
137 buf_resize(buf, old_len + len);
138}
139
140Cmp bigfloat_cmp(const BigFloat *op1, const BigFloat *op2) {
141 if (f128M_lt(&op1->value, &op2->value)) {
142 return CmpLT;
143 } else if (f128M_eq(&op1->value, &op2->value)) {
144 return CmpEQ;
145 } else {
146 return CmpGT;
147 }
148}
149
150float16_t bigfloat_to_f16(const BigFloat *bigfloat) {
151 return f128M_to_f16(&bigfloat->value);
152}
153
154float bigfloat_to_f32(const BigFloat *bigfloat) {
155 float32_t f32_value = f128M_to_f32(&bigfloat->value);
156 float result;
157 memcpy(&result, &f32_value, sizeof(float));
158 return result;
159}
160
161double bigfloat_to_f64(const BigFloat *bigfloat) {
162 float64_t f64_value = f128M_to_f64(&bigfloat->value);
163 double result;
164 memcpy(&result, &f64_value, sizeof(double));
165 return result;
166}
167
168float128_t bigfloat_to_f128(const BigFloat *bigfloat) {
169 return bigfloat->value;
170}
171
172Cmp bigfloat_cmp_zero(const BigFloat *bigfloat) {
173 float128_t zero_float;
174 ui32_to_f128M(0, &zero_float);
175 if (f128M_lt(&bigfloat->value, &zero_float)) {
176 return CmpLT;
177 } else if (f128M_eq(&bigfloat->value, &zero_float)) {
178 return CmpEQ;
179 } else {
180 return CmpGT;
181 }
182}
183
184bool bigfloat_has_fraction(const BigFloat *bigfloat) {
185 float128_t floored;
186 f128M_roundToInt(&bigfloat->value, softfloat_round_minMag, false, &floored);
187 return !f128M_eq(&floored, &bigfloat->value);
188}
189
190void bigfloat_sqrt(BigFloat *dest, const BigFloat *op) {
191 f128M_sqrt(&op->value, &dest->value);
192}
193
194void bigfloat_min(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
195 if (bigfloat_is_nan(op1)) {
196 bigfloat_init_bigfloat(dest, op2);
197 } else if (bigfloat_is_nan(op2)) {
198 bigfloat_init_bigfloat(dest, op1);
199 } else if (f128M_lt(&op1->value, &op2->value)) {
200 bigfloat_init_bigfloat(dest, op1);
201 } else {
202 bigfloat_init_bigfloat(dest, op2);
203 }
204}
205
206void bigfloat_max(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
207 if (bigfloat_is_nan(op1)) {
208 bigfloat_init_bigfloat(dest, op2);
209 } else if (bigfloat_is_nan(op2)) {
210 bigfloat_init_bigfloat(dest, op1);
211 } else if (f128M_lt(&op1->value, &op2->value)) {
212 bigfloat_init_bigfloat(dest, op2);
213 } else {
214 bigfloat_init_bigfloat(dest, op1);
215 }
216}
217
218bool bigfloat_is_nan(const BigFloat *op) {
219 return f128M_isSignalingNaN(&op->value);
220}
src/stage1/bigfloat.hpp deleted-60
...@@ -1,60 +0,0 @@
1/*
2 * Copyright (c) 2017 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_BIGFLOAT_HPP
9#define ZIG_BIGFLOAT_HPP
10
11#include "bigint.hpp"
12#include "error.hpp"
13#include <stdint.h>
14#include <stddef.h>
15
16#include "softfloat_types.h"
17
18
19struct BigFloat {
20 float128_t value;
21};
22
23struct Buf;
24
25void bigfloat_init_16(BigFloat *dest, float16_t x);
26void bigfloat_init_32(BigFloat *dest, float x);
27void bigfloat_init_64(BigFloat *dest, double x);
28void bigfloat_init_128(BigFloat *dest, float128_t x);
29void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x);
30void bigfloat_init_bigint(BigFloat *dest, const BigInt *op);
31Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr);
32
33float16_t bigfloat_to_f16(const BigFloat *bigfloat);
34float bigfloat_to_f32(const BigFloat *bigfloat);
35double bigfloat_to_f64(const BigFloat *bigfloat);
36float128_t bigfloat_to_f128(const BigFloat *bigfloat);
37
38void bigfloat_add(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
39void bigfloat_negate(BigFloat *dest, const BigFloat *op);
40void bigfloat_sub(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
41void bigfloat_mul(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
42void bigfloat_div(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
43void bigfloat_div_trunc(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
44void bigfloat_div_floor(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
45void bigfloat_rem(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
46void bigfloat_mod(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
47void bigfloat_sqrt(BigFloat *dest, const BigFloat *op);
48void bigfloat_min(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
49void bigfloat_max(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
50void bigfloat_append_buf(Buf *buf, const BigFloat *op);
51Cmp bigfloat_cmp(const BigFloat *op1, const BigFloat *op2);
52
53
54bool bigfloat_is_nan(const BigFloat *op);
55
56// convenience functions
57Cmp bigfloat_cmp_zero(const BigFloat *bigfloat);
58bool bigfloat_has_fraction(const BigFloat *bigfloat);
59
60#endif
src/stage1/bigint.cpp deleted-1895
...@@ -1,1895 +0,0 @@
1/*
2 * Copyright (c) 2017 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "bigfloat.hpp"
9#include "bigint.hpp"
10#include "buffer.hpp"
11#include "list.hpp"
12#include "os.hpp"
13#include "softfloat.hpp"
14
15#include <limits>
16#include <algorithm>
17
18static uint64_t bigint_as_unsigned(const BigInt *bigint);
19
20static void bigint_normalize(BigInt *dest) {
21 const uint64_t *digits = bigint_ptr(dest);
22
23 size_t last_nonzero_digit = SIZE_MAX;
24 for (size_t i = 0; i < dest->digit_count; i += 1) {
25 uint64_t digit = digits[i];
26 if (digit != 0) {
27 last_nonzero_digit = i;
28 }
29 }
30 if (last_nonzero_digit == SIZE_MAX) {
31 dest->is_negative = false;
32 dest->digit_count = 0;
33 } else {
34 dest->digit_count = last_nonzero_digit + 1;
35 if (last_nonzero_digit == 0) {
36 dest->data.digit = digits[0];
37 }
38 }
39}
40
41static uint8_t digit_to_char(uint8_t digit, bool uppercase) {
42 if (digit <= 9) {
43 return digit + '0';
44 } else if (digit <= 35) {
45 return (digit - 10) + (uppercase ? 'A' : 'a');
46 } else {
47 zig_unreachable();
48 }
49}
50
51size_t bigint_bits_needed(const BigInt *op) {
52 size_t full_bits = op->digit_count * 64;
53 size_t leading_zero_count = bigint_clz(op, full_bits);
54 size_t bits_needed = full_bits - leading_zero_count;
55 return bits_needed + op->is_negative;
56}
57
58static void to_twos_complement(BigInt *dest, const BigInt *op, size_t bit_count) {
59 if (bit_count == 0 || op->digit_count == 0) {
60 bigint_init_unsigned(dest, 0);
61 return;
62 }
63
64 BigInt pos_op = {0};
65
66 if (op->is_negative) {
67 BigInt negated = {0};
68 bigint_negate(&negated, op);
69
70 BigInt inverted = {0};
71 bigint_not(&inverted, &negated, bit_count, false);
72
73 BigInt one = {0};
74 bigint_init_unsigned(&one, 1);
75
76 bigint_add(&pos_op, &inverted, &one);
77 } else {
78 bigint_init_bigint(&pos_op, op);
79 }
80
81 dest->is_negative = false;
82 const uint64_t *op_digits = bigint_ptr(&pos_op);
83 if (pos_op.digit_count == 1) {
84 dest->data.digit = op_digits[0];
85 if (bit_count < 64) {
86 dest->data.digit &= (1ULL << bit_count) - 1;
87 }
88 dest->digit_count = 1;
89 bigint_normalize(dest);
90 return;
91 }
92 size_t digits_to_copy = bit_count / 64;
93 size_t leftover_bits = bit_count % 64;
94 dest->digit_count = digits_to_copy + ((leftover_bits == 0) ? 0 : 1);
95 if (dest->digit_count == 1) {
96 dest->data.digit = op_digits[0];
97 if (leftover_bits != 0) {
98 dest->data.digit &= (1ULL << leftover_bits) - 1;
99 }
100 if (dest->data.digit == 0) dest->digit_count = 0;
101 return;
102 }
103 dest->data.digits = heap::c_allocator.allocate_nonzero<uint64_t>(dest->digit_count);
104 for (size_t i = 0; i < digits_to_copy; i += 1) {
105 uint64_t digit = (i < pos_op.digit_count) ? op_digits[i] : 0;
106 dest->data.digits[i] = digit;
107 }
108 if (leftover_bits != 0) {
109 uint64_t digit = (digits_to_copy < pos_op.digit_count) ? op_digits[digits_to_copy] : 0;
110 dest->data.digits[digits_to_copy] = digit & ((1ULL << leftover_bits) - 1);
111 }
112 bigint_normalize(dest);
113}
114
115static bool bit_at_index(const BigInt *bi, size_t index) {
116 size_t digit_index = index / 64;
117 if (digit_index >= bi->digit_count)
118 return false;
119 size_t digit_bit_index = index % 64;
120 const uint64_t *digits = bigint_ptr(bi);
121 uint64_t digit = digits[digit_index];
122 return ((digit >> digit_bit_index) & 0x1) == 0x1;
123}
124
125static void from_twos_complement(BigInt *dest, const BigInt *src, size_t bit_count, bool is_signed) {
126 assert(!src->is_negative);
127
128 if (bit_count == 0 || src->digit_count == 0) {
129 bigint_init_unsigned(dest, 0);
130 return;
131 }
132
133 if (is_signed && bit_at_index(src, bit_count - 1)) {
134 BigInt negative_one = {0};
135 bigint_init_signed(&negative_one, -1);
136
137 BigInt minus_one = {0};
138 bigint_add(&minus_one, src, &negative_one);
139
140 BigInt inverted = {0};
141 bigint_not(&inverted, &minus_one, bit_count, false);
142
143 bigint_negate(dest, &inverted);
144 return;
145
146 }
147
148 bigint_init_bigint(dest, src);
149}
150
151void bigint_init_unsigned(BigInt *dest, uint64_t x) {
152 if (x == 0) {
153 dest->digit_count = 0;
154 dest->is_negative = false;
155 return;
156 }
157 dest->digit_count = 1;
158 dest->data.digit = x;
159 dest->is_negative = false;
160}
161
162void bigint_init_signed(BigInt *dest, int64_t x) {
163 if (x >= 0) {
164 return bigint_init_unsigned(dest, x);
165 }
166 dest->is_negative = true;
167 dest->digit_count = 1;
168 dest->data.digit = ((uint64_t)(-(x + 1))) + 1;
169}
170
171void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative) {
172 if (digit_count == 0) {
173 return bigint_init_unsigned(dest, 0);
174 } else if (digit_count == 1) {
175 dest->digit_count = 1;
176 dest->data.digit = digits[0];
177 dest->is_negative = is_negative;
178 bigint_normalize(dest);
179 return;
180 }
181
182 dest->digit_count = digit_count;
183 dest->is_negative = is_negative;
184 dest->data.digits = heap::c_allocator.allocate_nonzero<uint64_t>(digit_count);
185 memcpy(dest->data.digits, digits, sizeof(uint64_t) * digit_count);
186
187 bigint_normalize(dest);
188}
189
190void bigint_init_bigint(BigInt *dest, const BigInt *src) {
191 if (src->digit_count == 0) {
192 return bigint_init_unsigned(dest, 0);
193 } else if (src->digit_count == 1) {
194 dest->digit_count = 1;
195 dest->data.digit = src->data.digit;
196 dest->is_negative = src->is_negative;
197 return;
198 }
199 dest->is_negative = src->is_negative;
200 dest->digit_count = src->digit_count;
201 dest->data.digits = heap::c_allocator.allocate_nonzero<uint64_t>(dest->digit_count);
202 memcpy(dest->data.digits, src->data.digits, sizeof(uint64_t) * dest->digit_count);
203}
204
205void bigint_deinit(BigInt *bi) {
206 if (bi->digit_count > 1)
207 heap::c_allocator.deallocate(bi->data.digits, bi->digit_count);
208}
209
210void bigint_init_bigfloat(BigInt *dest, const BigFloat *op) {
211 float128_t zero;
212 ui32_to_f128M(0, &zero);
213
214 dest->is_negative = f128M_lt(&op->value, &zero);
215 float128_t abs_val;
216 if (dest->is_negative) {
217 f128M_sub(&zero, &op->value, &abs_val);
218 } else {
219 memcpy(&abs_val, &op->value, sizeof(float128_t));
220 }
221
222 float128_t max_u64;
223 ui64_to_f128M(UINT64_MAX, &max_u64);
224 if (f128M_le(&abs_val, &max_u64)) {
225 dest->digit_count = 1;
226 dest->data.digit = f128M_to_ui64(&abs_val, softfloat_round_minMag, false);
227 bigint_normalize(dest);
228 return;
229 }
230
231 float128_t amt;
232 f128M_div(&abs_val, &max_u64, &amt);
233 float128_t remainder;
234 f128M_rem(&abs_val, &max_u64, &remainder);
235
236 dest->digit_count = 2;
237 dest->data.digits = heap::c_allocator.allocate_nonzero<uint64_t>(dest->digit_count);
238 dest->data.digits[0] = f128M_to_ui64(&remainder, softfloat_round_minMag, false);
239 dest->data.digits[1] = f128M_to_ui64(&amt, softfloat_round_minMag, false);
240 bigint_normalize(dest);
241}
242
243bool bigint_fits_in_bits(const BigInt *bn, size_t bit_count, bool is_signed) {
244 assert(bn->digit_count != 1 || bn->data.digit != 0);
245 if (bit_count == 0) {
246 return bigint_cmp_zero(bn) == CmpEQ;
247 }
248 if (bn->digit_count == 0) {
249 return true;
250 }
251
252 if (!is_signed) {
253 if(bn->is_negative) return false;
254 size_t full_bits = bn->digit_count * 64;
255 size_t leading_zero_count = bigint_clz(bn, full_bits);
256 return bit_count >= full_bits - leading_zero_count;
257 }
258
259 BigInt one = {0};
260 bigint_init_unsigned(&one, 1);
261
262 BigInt shl_amt = {0};
263 bigint_init_unsigned(&shl_amt, bit_count - 1);
264
265 BigInt max_value_plus_one = {0};
266 bigint_shl(&max_value_plus_one, &one, &shl_amt);
267
268 BigInt max_value = {0};
269 bigint_sub(&max_value, &max_value_plus_one, &one);
270
271 BigInt min_value = {0};
272 bigint_negate(&min_value, &max_value_plus_one);
273
274 Cmp min_cmp = bigint_cmp(bn, &min_value);
275 Cmp max_cmp = bigint_cmp(bn, &max_value);
276
277 return (min_cmp == CmpGT || min_cmp == CmpEQ) && (max_cmp == CmpLT || max_cmp == CmpEQ);
278}
279
280void bigint_write_twos_complement(const BigInt *big_int, uint8_t *buf, size_t bit_count, bool is_big_endian) {
281 if (bit_count == 0)
282 return;
283
284 BigInt twos_comp = {0};
285 to_twos_complement(&twos_comp, big_int, bit_count);
286
287 const uint64_t *twos_comp_digits = bigint_ptr(&twos_comp);
288
289 size_t bits_in_last_digit = bit_count % 64;
290 if (bits_in_last_digit == 0) bits_in_last_digit = 64;
291 size_t bytes_in_last_digit = (bits_in_last_digit + 7) / 8;
292 size_t unwritten_byte_count = 8 - bytes_in_last_digit;
293
294 if (is_big_endian) {
295 size_t last_digit_index = (bit_count - 1) / 64;
296 size_t digit_index = last_digit_index;
297 size_t buf_index = 0;
298 for (;;) {
299 uint64_t x = (digit_index < twos_comp.digit_count) ? twos_comp_digits[digit_index] : 0;
300
301 for (size_t byte_index = 7;;) {
302 uint8_t byte = x & 0xff;
303 if (digit_index == last_digit_index) {
304 buf[buf_index + byte_index - unwritten_byte_count] = byte;
305 if (byte_index == unwritten_byte_count) break;
306 } else {
307 buf[buf_index + byte_index] = byte;
308 }
309
310 if (byte_index == 0) break;
311 byte_index -= 1;
312 x >>= 8;
313 }
314
315 if (digit_index == 0) break;
316 if (digit_index == last_digit_index) {
317 buf_index += bytes_in_last_digit;
318 } else {
319 buf_index += 8;
320 }
321 digit_index -= 1;
322 }
323 } else {
324 size_t digit_count = (bit_count + 63) / 64;
325 size_t buf_index = 0;
326 for (size_t digit_index = 0; digit_index < digit_count; digit_index += 1) {
327 uint64_t x = (digit_index < twos_comp.digit_count) ? twos_comp_digits[digit_index] : 0;
328
329 for (size_t byte_index = 0;
330 byte_index < 8 && (digit_index + 1 < digit_count || byte_index < bytes_in_last_digit);
331 byte_index += 1)
332 {
333 uint8_t byte = x & 0xff;
334 buf[buf_index] = byte;
335 buf_index += 1;
336 x >>= 8;
337 }
338 }
339 }
340}
341
342
343void bigint_read_twos_complement(BigInt *dest, const uint8_t *buf, size_t bit_count, bool is_big_endian,
344 bool is_signed)
345{
346 if (bit_count == 0) {
347 bigint_init_unsigned(dest, 0);
348 return;
349 }
350
351 dest->digit_count = (bit_count + 63) / 64;
352 uint64_t *digits;
353 if (dest->digit_count == 1) {
354 digits = &dest->data.digit;
355 } else {
356 digits = heap::c_allocator.allocate_nonzero<uint64_t>(dest->digit_count);
357 dest->data.digits = digits;
358 }
359
360 size_t bits_in_last_digit = bit_count % 64;
361 if (bits_in_last_digit == 0) {
362 bits_in_last_digit = 64;
363 }
364 size_t bytes_in_last_digit = (bits_in_last_digit + 7) / 8;
365 size_t unread_byte_count = 8 - bytes_in_last_digit;
366
367 if (is_big_endian) {
368 size_t buf_index = 0;
369 uint64_t digit = 0;
370 for (size_t byte_index = unread_byte_count; byte_index < 8; byte_index += 1) {
371 uint8_t byte = buf[buf_index];
372 buf_index += 1;
373 digit <<= 8;
374 digit |= byte;
375 }
376 digits[dest->digit_count - 1] = digit;
377 for (size_t digit_index = 1; digit_index < dest->digit_count; digit_index += 1) {
378 digit = 0;
379 for (size_t byte_index = 0; byte_index < 8; byte_index += 1) {
380 uint8_t byte = buf[buf_index];
381 buf_index += 1;
382 digit <<= 8;
383 digit |= byte;
384 }
385 digits[dest->digit_count - 1 - digit_index] = digit;
386 }
387 } else {
388 size_t buf_index = 0;
389 for (size_t digit_index = 0; digit_index < dest->digit_count; digit_index += 1) {
390 uint64_t digit = 0;
391 size_t end_byte_index = (digit_index == dest->digit_count - 1) ? bytes_in_last_digit : 8;
392 for (size_t byte_index = 0; byte_index < end_byte_index; byte_index += 1) {
393 uint64_t byte = buf[buf_index];
394 buf_index += 1;
395
396 digit |= byte << (8 * byte_index);
397 }
398 digits[digit_index] = digit;
399 }
400 }
401
402 if (is_signed) {
403 bigint_normalize(dest);
404 BigInt tmp = {0};
405 bigint_init_bigint(&tmp, dest);
406 from_twos_complement(dest, &tmp, bit_count, true);
407 } else {
408 dest->is_negative = false;
409 bigint_normalize(dest);
410 }
411}
412
413#if defined(_MSC_VER)
414static bool add_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
415 *result = op1 + op2;
416 return *result < op1 || *result < op2;
417}
418
419static bool sub_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
420 *result = op1 - op2;
421 return *result > op1;
422}
423
424bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
425 *result = op1 * op2;
426
427 if (op1 == 0 || op2 == 0)
428 return false;
429
430 if (op1 > UINT64_MAX / op2)
431 return true;
432
433 if (op2 > UINT64_MAX / op1)
434 return true;
435
436 return false;
437}
438#else
439static bool add_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
440 return __builtin_uaddll_overflow((unsigned long long)op1, (unsigned long long)op2,
441 (unsigned long long *)result);
442}
443
444static bool sub_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
445 return __builtin_usubll_overflow((unsigned long long)op1, (unsigned long long)op2,
446 (unsigned long long *)result);
447}
448
449bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
450 return __builtin_umulll_overflow((unsigned long long)op1, (unsigned long long)op2,
451 (unsigned long long *)result);
452}
453#endif
454
455void bigint_max(BigInt* dest, const BigInt *op1, const BigInt *op2) {
456 switch (bigint_cmp(op1, op2)) {
457 case CmpEQ:
458 case CmpLT:
459 return bigint_init_bigint(dest, op2);
460 case CmpGT:
461 return bigint_init_bigint(dest, op1);
462 }
463}
464
465void bigint_min(BigInt* dest, const BigInt *op1, const BigInt *op2) {
466 switch (bigint_cmp(op1, op2)) {
467 case CmpEQ:
468 case CmpLT:
469 return bigint_init_bigint(dest, op1);
470 case CmpGT:
471 return bigint_init_bigint(dest, op2);
472 }
473}
474
475/// clamps op within bit_count/signedness boundaries
476/// signed bounds are [-2^(bit_count-1)..2^(bit_count-1)-1]
477/// unsigned bounds are [0..2^bit_count-1]
478void bigint_clamp_by_bitcount(BigInt* dest, uint32_t bit_count, bool is_signed) {
479 bool is_negative = dest->is_negative;
480 // unsigned and dest->is_negative => clamp to 0
481 if (is_negative && !is_signed) {
482 bigint_deinit(dest);
483 bigint_init_unsigned(dest, 0);
484 return;
485 }
486 // compute the number of bits required to store the value, and use that
487 // to decide whether to clamp the result
488 // to workaround the fact this bits_needed calculation would yield 65 or more for
489 // all negative numbers, set is_negative to false. this is a cheap way to find
490 // bits_needed(abs(dest)).
491 dest->is_negative = false;
492 // because we've set is_negative to false, we have to account for the extra bit here
493 // by adding 1 additional bit_needed when (is_negative && !is_signed).
494 size_t full_bits = dest->digit_count * 64;
495 size_t leading_zero_count = bigint_clz(dest, full_bits);
496 size_t bits_needed = full_bits - leading_zero_count + (is_negative && !is_signed);
497
498 bit_count -= is_signed;
499 if(bits_needed > bit_count) {
500 BigInt one;
501 bigint_init_unsigned(&one, 1);
502 BigInt bit_count_big;
503 bigint_init_unsigned(&bit_count_big, bit_count);
504
505 if(is_signed) {
506 if(is_negative) {
507 BigInt bound;
508 bigint_shl(&bound, &one, &bit_count_big);
509 bigint_deinit(dest);
510 *dest = bound;
511 } else {
512 BigInt bound;
513 bigint_shl(&bound, &one, &bit_count_big);
514 BigInt bound_sub_one;
515 bigint_sub(&bound_sub_one, &bound, &one);
516 bigint_deinit(&bound);
517 bigint_deinit(dest);
518 *dest = bound_sub_one;
519 }
520 } else {
521 BigInt bound;
522 bigint_shl(&bound, &one, &bit_count_big);
523 BigInt bound_sub_one;
524 bigint_sub(&bound_sub_one, &bound, &one);
525 bigint_deinit(&bound);
526 bigint_deinit(dest);
527 *dest = bound_sub_one;
528 }
529 }
530 dest->is_negative = is_negative;
531}
532
533void bigint_add_sat(BigInt* dest, const BigInt *op1, const BigInt *op2, uint32_t bit_count, bool is_signed) {
534 bigint_add(dest, op1, op2);
535 bigint_clamp_by_bitcount(dest, bit_count, is_signed);
536}
537
538void bigint_sub_sat(BigInt* dest, const BigInt *op1, const BigInt *op2, uint32_t bit_count, bool is_signed) {
539 bigint_sub(dest, op1, op2);
540 bigint_clamp_by_bitcount(dest, bit_count, is_signed);
541}
542
543void bigint_mul_sat(BigInt* dest, const BigInt *op1, const BigInt *op2, uint32_t bit_count, bool is_signed) {
544 bigint_mul(dest, op1, op2);
545 bigint_clamp_by_bitcount(dest, bit_count, is_signed);
546}
547
548void bigint_shl_sat(BigInt* dest, const BigInt *op1, const BigInt *op2, uint32_t bit_count, bool is_signed) {
549 bigint_shl(dest, op1, op2);
550 bigint_clamp_by_bitcount(dest, bit_count, is_signed);
551}
552
553void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) {
554 if (op1->digit_count == 0) {
555 return bigint_init_bigint(dest, op2);
556 }
557 if (op2->digit_count == 0) {
558 return bigint_init_bigint(dest, op1);
559 }
560 if (op1->is_negative == op2->is_negative) {
561 dest->is_negative = op1->is_negative;
562
563 const uint64_t *op1_digits = bigint_ptr(op1);
564 const uint64_t *op2_digits = bigint_ptr(op2);
565 bool overflow = add_u64_overflow(op1_digits[0], op2_digits[0], &dest->data.digit);
566 if (overflow == 0 && op1->digit_count == 1 && op2->digit_count == 1) {
567 dest->digit_count = 1;
568 bigint_normalize(dest);
569 return;
570 }
571 size_t i = 1;
572 uint64_t first_digit = dest->data.digit;
573 dest->data.digits = heap::c_allocator.allocate_nonzero<uint64_t>(max(op1->digit_count, op2->digit_count) + 1);
574 dest->data.digits[0] = first_digit;
575
576 for (;;) {
577 bool found_digit = false;
578 uint64_t x = overflow;
579 overflow = 0;
580
581 if (i < op1->digit_count) {
582 found_digit = true;
583 uint64_t digit = op1_digits[i];
584 overflow += add_u64_overflow(x, digit, &x);
585 }
586
587 if (i < op2->digit_count) {
588 found_digit = true;
589 uint64_t digit = op2_digits[i];
590 overflow += add_u64_overflow(x, digit, &x);
591 }
592
593 dest->data.digits[i] = x;
594 i += 1;
595
596 if (!found_digit) {
597 dest->digit_count = i;
598 bigint_normalize(dest);
599 return;
600 }
601 }
602 }
603 const BigInt *op_pos;
604 const BigInt *op_neg;
605 if (op1->is_negative) {
606 op_neg = op1;
607 op_pos = op2;
608 } else {
609 op_pos = op1;
610 op_neg = op2;
611 }
612
613 BigInt op_neg_abs = {0};
614 bigint_negate(&op_neg_abs, op_neg);
615 const BigInt *bigger_op;
616 const BigInt *smaller_op;
617 switch (bigint_cmp(op_pos, &op_neg_abs)) {
618 case CmpEQ:
619 bigint_init_unsigned(dest, 0);
620 return;
621 case CmpLT:
622 bigger_op = &op_neg_abs;
623 smaller_op = op_pos;
624 dest->is_negative = true;
625 break;
626 case CmpGT:
627 bigger_op = op_pos;
628 smaller_op = &op_neg_abs;
629 dest->is_negative = false;
630 break;
631 }
632 const uint64_t *bigger_op_digits = bigint_ptr(bigger_op);
633 const uint64_t *smaller_op_digits = bigint_ptr(smaller_op);
634 uint64_t overflow = sub_u64_overflow(bigger_op_digits[0], smaller_op_digits[0], &dest->data.digit);
635 if (overflow == 0 && bigger_op->digit_count == 1 && smaller_op->digit_count == 1) {
636 dest->digit_count = 1;
637 bigint_normalize(dest);
638 return;
639 }
640 uint64_t first_digit = dest->data.digit;
641 dest->data.digits = heap::c_allocator.allocate_nonzero<uint64_t>(bigger_op->digit_count);
642 dest->data.digits[0] = first_digit;
643 size_t i = 1;
644
645 for (;;) {
646 uint64_t x = bigger_op_digits[i];
647 uint64_t prev_overflow = overflow;
648 overflow = 0;
649
650 if (i < smaller_op->digit_count) {
651 uint64_t digit = smaller_op_digits[i];
652 overflow += sub_u64_overflow(x, digit, &x);
653 }
654
655 overflow += sub_u64_overflow(x, prev_overflow, &x);
656 dest->data.digits[i] = x;
657 i += 1;
658
659 if (i >= bigger_op->digit_count) {
660 break;
661 }
662 }
663 assert(overflow == 0);
664 dest->digit_count = i;
665 bigint_normalize(dest);
666}
667
668void bigint_add_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed) {
669 BigInt unwrapped = {0};
670 bigint_add(&unwrapped, op1, op2);
671 bigint_truncate(dest, &unwrapped, bit_count, is_signed);
672}
673
674void bigint_sub(BigInt *dest, const BigInt *op1, const BigInt *op2) {
675 BigInt op2_negated = {0};
676 bigint_negate(&op2_negated, op2);
677 return bigint_add(dest, op1, &op2_negated);
678}
679
680void bigint_sub_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed) {
681 BigInt op2_negated = {0};
682 bigint_negate(&op2_negated, op2);
683 return bigint_add_wrap(dest, op1, &op2_negated, bit_count, is_signed);
684}
685
686static void mul_overflow(uint64_t op1, uint64_t op2, uint64_t *lo, uint64_t *hi) {
687 uint64_t u1 = (op1 & 0xffffffff);
688 uint64_t v1 = (op2 & 0xffffffff);
689 uint64_t t = (u1 * v1);
690 uint64_t w3 = (t & 0xffffffff);
691 uint64_t k = (t >> 32);
692
693 op1 >>= 32;
694 t = (op1 * v1) + k;
695 k = (t & 0xffffffff);
696 uint64_t w1 = (t >> 32);
697
698 op2 >>= 32;
699 t = (u1 * op2) + k;
700 k = (t >> 32);
701
702 *hi = (op1 * op2) + w1 + k;
703 *lo = (t << 32) + w3;
704}
705
706static void mul_scalar(BigInt *dest, const BigInt *op, uint64_t scalar) {
707 bigint_init_unsigned(dest, 0);
708
709 BigInt bi_64;
710 bigint_init_unsigned(&bi_64, 64);
711
712 const uint64_t *op_digits = bigint_ptr(op);
713 size_t i = op->digit_count - 1;
714
715 for (;;) {
716 BigInt shifted;
717 bigint_shl(&shifted, dest, &bi_64);
718
719 uint64_t result_scalar;
720 uint64_t carry_scalar;
721 mul_overflow(scalar, op_digits[i], &result_scalar, &carry_scalar);
722
723 BigInt result;
724 bigint_init_unsigned(&result, result_scalar);
725
726 BigInt carry;
727 bigint_init_unsigned(&carry, carry_scalar);
728
729 BigInt carry_shifted;
730 bigint_shl(&carry_shifted, &carry, &bi_64);
731
732 BigInt tmp;
733 bigint_add(&tmp, &shifted, &carry_shifted);
734
735 bigint_add(dest, &tmp, &result);
736
737 if (i == 0) {
738 break;
739 }
740 i -= 1;
741 }
742}
743
744void bigint_mul(BigInt *dest, const BigInt *op1, const BigInt *op2) {
745 if (op1->digit_count == 0 || op2->digit_count == 0) {
746 return bigint_init_unsigned(dest, 0);
747 }
748 const uint64_t *op1_digits = bigint_ptr(op1);
749 const uint64_t *op2_digits = bigint_ptr(op2);
750
751 uint64_t carry;
752 mul_overflow(op1_digits[0], op2_digits[0], &dest->data.digit, &carry);
753 if (carry == 0 && op1->digit_count == 1 && op2->digit_count == 1) {
754 dest->is_negative = (op1->is_negative != op2->is_negative);
755 dest->digit_count = 1;
756 bigint_normalize(dest);
757 return;
758 }
759
760 bigint_init_unsigned(dest, 0);
761
762 BigInt bi_64;
763 bigint_init_unsigned(&bi_64, 64);
764
765 size_t i = op2->digit_count - 1;
766 for (;;) {
767 BigInt shifted;
768 bigint_shl(&shifted, dest, &bi_64);
769
770 BigInt scalar_result;
771 mul_scalar(&scalar_result, op1, op2_digits[i]);
772
773 bigint_add(dest, &scalar_result, &shifted);
774
775 if (i == 0) {
776 break;
777 }
778 i -= 1;
779 }
780
781 dest->is_negative = (op1->is_negative != op2->is_negative);
782 bigint_normalize(dest);
783}
784
785void bigint_mul_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed) {
786 BigInt unwrapped = {0};
787 bigint_mul(&unwrapped, op1, op2);
788 bigint_truncate(dest, &unwrapped, bit_count, is_signed);
789}
790
791enum ZeroBehavior {
792 /// \brief The returned value is undefined.
793 ZB_Undefined,
794 /// \brief The returned value is numeric_limits<T>::max()
795 ZB_Max,
796 /// \brief The returned value is numeric_limits<T>::digits
797 ZB_Width
798};
799
800template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
801 static std::size_t count(T Val, ZeroBehavior) {
802 if (!Val)
803 return std::numeric_limits<T>::digits;
804
805 // Bisection method.
806 std::size_t ZeroBits = 0;
807 for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
808 T Tmp = Val >> Shift;
809 if (Tmp)
810 Val = Tmp;
811 else
812 ZeroBits |= Shift;
813 }
814 return ZeroBits;
815 }
816};
817
818#if __GNUC__ >= 4 || defined(_MSC_VER)
819template <typename T> struct LeadingZerosCounter<T, 4> {
820 static std::size_t count(T Val, ZeroBehavior ZB) {
821 if (ZB != ZB_Undefined && Val == 0)
822 return 32;
823
824#if defined(_MSC_VER)
825 unsigned long Index;
826 _BitScanReverse(&Index, Val);
827 return Index ^ 31;
828#else
829 return __builtin_clz(Val);
830#endif
831 }
832};
833
834#if !defined(_MSC_VER) || defined(_M_X64)
835template <typename T> struct LeadingZerosCounter<T, 8> {
836 static std::size_t count(T Val, ZeroBehavior ZB) {
837 if (ZB != ZB_Undefined && Val == 0)
838 return 64;
839
840#if defined(_MSC_VER)
841 unsigned long Index;
842 _BitScanReverse64(&Index, Val);
843 return Index ^ 63;
844#else
845 return __builtin_clzll(Val);
846#endif
847 }
848};
849#endif
850#endif
851
852/// \brief Count number of 0's from the most significant bit to the least
853/// stopping at the first 1.
854///
855/// Only unsigned integral types are allowed.
856///
857/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
858/// valid arguments.
859template <typename T>
860std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
861 static_assert(std::numeric_limits<T>::is_integer &&
862 !std::numeric_limits<T>::is_signed,
863 "Only unsigned integral types are allowed.");
864 return LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB);
865}
866
867/// Make a 64-bit integer from a high / low pair of 32-bit integers.
868constexpr inline uint64_t Make_64(uint32_t High, uint32_t Low) {
869 return ((uint64_t)High << 32) | (uint64_t)Low;
870}
871
872/// Return the high 32 bits of a 64 bit value.
873constexpr inline uint32_t Hi_32(uint64_t Value) {
874 return static_cast<uint32_t>(Value >> 32);
875}
876
877/// Return the low 32 bits of a 64 bit value.
878constexpr inline uint32_t Lo_32(uint64_t Value) {
879 return static_cast<uint32_t>(Value);
880}
881
882/// Implementation of Knuth's Algorithm D (Division of nonnegative integers)
883/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The
884/// variables here have the same names as in the algorithm. Comments explain
885/// the algorithm and any deviation from it.
886static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
887 unsigned m, unsigned n)
888{
889 assert(u && "Must provide dividend");
890 assert(v && "Must provide divisor");
891 assert(q && "Must provide quotient");
892 assert(u != v && u != q && v != q && "Must use different memory");
893 assert(n>1 && "n must be > 1");
894
895 // b denotes the base of the number system. In our case b is 2^32.
896 const uint64_t b = uint64_t(1) << 32;
897
898 // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of
899 // u and v by d. Note that we have taken Knuth's advice here to use a power
900 // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of
901 // 2 allows us to shift instead of multiply and it is easy to determine the
902 // shift amount from the leading zeros. We are basically normalizing the u
903 // and v so that its high bits are shifted to the top of v's range without
904 // overflow. Note that this can require an extra word in u so that u must
905 // be of length m+n+1.
906 unsigned shift = countLeadingZeros(v[n-1]);
907 uint32_t v_carry = 0;
908 uint32_t u_carry = 0;
909 if (shift) {
910 for (unsigned i = 0; i < m+n; ++i) {
911 uint32_t u_tmp = u[i] >> (32 - shift);
912 u[i] = (u[i] << shift) | u_carry;
913 u_carry = u_tmp;
914 }
915 for (unsigned i = 0; i < n; ++i) {
916 uint32_t v_tmp = v[i] >> (32 - shift);
917 v[i] = (v[i] << shift) | v_carry;
918 v_carry = v_tmp;
919 }
920 }
921 u[m+n] = u_carry;
922
923 // D2. [Initialize j.] Set j to m. This is the loop counter over the places.
924 int j = m;
925 do {
926 // D3. [Calculate q'.].
927 // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q')
928 // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r')
929 // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease
930 // qp by 1, increase rp by v[n-1], and repeat this test if rp < b. The test
931 // on v[n-2] determines at high speed most of the cases in which the trial
932 // value qp is one too large, and it eliminates all cases where qp is two
933 // too large.
934 uint64_t dividend = Make_64(u[j+n], u[j+n-1]);
935 uint64_t qp = dividend / v[n-1];
936 uint64_t rp = dividend % v[n-1];
937 if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) {
938 qp--;
939 rp += v[n-1];
940 if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2]))
941 qp--;
942 }
943
944 // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with
945 // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation
946 // consists of a simple multiplication by a one-place number, combined with
947 // a subtraction.
948 // The digits (u[j+n]...u[j]) should be kept positive; if the result of
949 // this step is actually negative, (u[j+n]...u[j]) should be left as the
950 // true value plus b**(n+1), namely as the b's complement of
951 // the true value, and a "borrow" to the left should be remembered.
952 int64_t borrow = 0;
953 for (unsigned i = 0; i < n; ++i) {
954 uint64_t p = uint64_t(qp) * uint64_t(v[i]);
955 int64_t subres = int64_t(u[j+i]) - borrow - Lo_32(p);
956 u[j+i] = Lo_32(subres);
957 borrow = Hi_32(p) - Hi_32(subres);
958 }
959 bool isNeg = u[j+n] < borrow;
960 u[j+n] -= Lo_32(borrow);
961
962 // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was
963 // negative, go to step D6; otherwise go on to step D7.
964 q[j] = Lo_32(qp);
965 if (isNeg) {
966 // D6. [Add back]. The probability that this step is necessary is very
967 // small, on the order of only 2/b. Make sure that test data accounts for
968 // this possibility. Decrease q[j] by 1
969 q[j]--;
970 // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]).
971 // A carry will occur to the left of u[j+n], and it should be ignored
972 // since it cancels with the borrow that occurred in D4.
973 bool carry = false;
974 for (unsigned i = 0; i < n; i++) {
975 uint32_t limit = std::min(u[j+i],v[i]);
976 u[j+i] += v[i] + carry;
977 carry = u[j+i] < limit || (carry && u[j+i] == limit);
978 }
979 u[j+n] += carry;
980 }
981
982 // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3.
983 } while (--j >= 0);
984
985 // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired
986 // remainder may be obtained by dividing u[...] by d. If r is non-null we
987 // compute the remainder (urem uses this).
988 if (r) {
989 // The value d is expressed by the "shift" value above since we avoided
990 // multiplication by d by using a shift left. So, all we have to do is
991 // shift right here.
992 if (shift) {
993 uint32_t carry = 0;
994 for (int i = n-1; i >= 0; i--) {
995 r[i] = (u[i] >> shift) | carry;
996 carry = u[i] << (32 - shift);
997 }
998 } else {
999 for (int i = n-1; i >= 0; i--) {
1000 r[i] = u[i];
1001 }
1002 }
1003 }
1004}
1005
1006// Implementation ported from LLVM/lib/Support/APInt.cpp
1007static void bigint_unsigned_division(const BigInt *op1, const BigInt *op2, BigInt *Quotient, BigInt *Remainder) {
1008 Cmp cmp = bigint_cmp(op1, op2);
1009 if (cmp == CmpLT) {
1010 if (Quotient != nullptr) {
1011 bigint_init_unsigned(Quotient, 0);
1012 }
1013 if (Remainder != nullptr) {
1014 bigint_init_bigint(Remainder, op1);
1015 }
1016 return;
1017 }
1018 if (cmp == CmpEQ) {
1019 if (Quotient != nullptr) {
1020 bigint_init_unsigned(Quotient, 1);
1021 }
1022 if (Remainder != nullptr) {
1023 bigint_init_unsigned(Remainder, 0);
1024 }
1025 return;
1026 }
1027
1028 const uint64_t *LHS = bigint_ptr(op1);
1029 const uint64_t *RHS = bigint_ptr(op2);
1030 unsigned lhsWords = op1->digit_count;
1031 unsigned rhsWords = op2->digit_count;
1032
1033 // First, compose the values into an array of 32-bit words instead of
1034 // 64-bit words. This is a necessity of both the "short division" algorithm
1035 // and the Knuth "classical algorithm" which requires there to be native
1036 // operations for +, -, and * on an m bit value with an m*2 bit result. We
1037 // can't use 64-bit operands here because we don't have native results of
1038 // 128-bits. Furthermore, casting the 64-bit values to 32-bit values won't
1039 // work on large-endian machines.
1040 unsigned n = rhsWords * 2;
1041 unsigned m = (lhsWords * 2) - n;
1042
1043 // Allocate space for the temporary values we need either on the stack, if
1044 // it will fit, or on the heap if it won't.
1045 uint32_t SPACE[128];
1046 uint32_t *U = nullptr;
1047 uint32_t *V = nullptr;
1048 uint32_t *Q = nullptr;
1049 uint32_t *R = nullptr;
1050 if ((Remainder?4:3)*n+2*m+1 <= 128) {
1051 U = &SPACE[0];
1052 V = &SPACE[m+n+1];
1053 Q = &SPACE[(m+n+1) + n];
1054 if (Remainder)
1055 R = &SPACE[(m+n+1) + n + (m+n)];
1056 } else {
1057 U = new uint32_t[m + n + 1];
1058 V = new uint32_t[n];
1059 Q = new uint32_t[m+n];
1060 if (Remainder)
1061 R = new uint32_t[n];
1062 }
1063
1064 // Initialize the dividend
1065 memset(U, 0, (m+n+1)*sizeof(uint32_t));
1066 for (unsigned i = 0; i < lhsWords; ++i) {
1067 uint64_t tmp = LHS[i];
1068 U[i * 2] = Lo_32(tmp);
1069 U[i * 2 + 1] = Hi_32(tmp);
1070 }
1071 U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm.
1072
1073 // Initialize the divisor
1074 memset(V, 0, (n)*sizeof(uint32_t));
1075 for (unsigned i = 0; i < rhsWords; ++i) {
1076 uint64_t tmp = RHS[i];
1077 V[i * 2] = Lo_32(tmp);
1078 V[i * 2 + 1] = Hi_32(tmp);
1079 }
1080
1081 // initialize the quotient and remainder
1082 memset(Q, 0, (m+n) * sizeof(uint32_t));
1083 if (Remainder)
1084 memset(R, 0, n * sizeof(uint32_t));
1085
1086 // Now, adjust m and n for the Knuth division. n is the number of words in
1087 // the divisor. m is the number of words by which the dividend exceeds the
1088 // divisor (i.e. m+n is the length of the dividend). These sizes must not
1089 // contain any zero words or the Knuth algorithm fails.
1090 for (unsigned i = n; i > 0 && V[i-1] == 0; i--) {
1091 n--;
1092 m++;
1093 }
1094 for (unsigned i = m+n; i > 0 && U[i-1] == 0; i--)
1095 m--;
1096
1097 // If we're left with only a single word for the divisor, Knuth doesn't work
1098 // so we implement the short division algorithm here. This is much simpler
1099 // and faster because we are certain that we can divide a 64-bit quantity
1100 // by a 32-bit quantity at hardware speed and short division is simply a
1101 // series of such operations. This is just like doing short division but we
1102 // are using base 2^32 instead of base 10.
1103 assert(n != 0 && "Divide by zero?");
1104 if (n == 1) {
1105 uint32_t divisor = V[0];
1106 uint32_t remainder = 0;
1107 for (int i = m; i >= 0; i--) {
1108 uint64_t partial_dividend = Make_64(remainder, U[i]);
1109 if (partial_dividend == 0) {
1110 Q[i] = 0;
1111 remainder = 0;
1112 } else if (partial_dividend < divisor) {
1113 Q[i] = 0;
1114 remainder = Lo_32(partial_dividend);
1115 } else if (partial_dividend == divisor) {
1116 Q[i] = 1;
1117 remainder = 0;
1118 } else {
1119 Q[i] = Lo_32(partial_dividend / divisor);
1120 remainder = Lo_32(partial_dividend - (Q[i] * divisor));
1121 }
1122 }
1123 if (R)
1124 R[0] = remainder;
1125 } else {
1126 // Now we're ready to invoke the Knuth classical divide algorithm. In this
1127 // case n > 1.
1128 KnuthDiv(U, V, Q, R, m, n);
1129 }
1130
1131 // If the caller wants the quotient
1132 if (Quotient) {
1133 Quotient->is_negative = false;
1134 Quotient->digit_count = lhsWords;
1135 if (lhsWords == 1) {
1136 Quotient->data.digit = Make_64(Q[1], Q[0]);
1137 } else {
1138 Quotient->data.digits = heap::c_allocator.allocate<uint64_t>(lhsWords);
1139 for (size_t i = 0; i < lhsWords; i += 1) {
1140 Quotient->data.digits[i] = Make_64(Q[i*2+1], Q[i*2]);
1141 }
1142 }
1143 }
1144
1145 // If the caller wants the remainder
1146 if (Remainder) {
1147 Remainder->is_negative = false;
1148 Remainder->digit_count = rhsWords;
1149 if (rhsWords == 1) {
1150 Remainder->data.digit = Make_64(R[1], R[0]);
1151 } else {
1152 Remainder->data.digits = heap::c_allocator.allocate<uint64_t>(rhsWords);
1153 for (size_t i = 0; i < rhsWords; i += 1) {
1154 Remainder->data.digits[i] = Make_64(R[i*2+1], R[i*2]);
1155 }
1156 }
1157 }
1158}
1159
1160void bigint_div_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1161 assert(op2->digit_count != 0); // division by zero
1162 if (op1->digit_count == 0) {
1163 bigint_init_unsigned(dest, 0);
1164 return;
1165 }
1166 const uint64_t *op1_digits = bigint_ptr(op1);
1167 const uint64_t *op2_digits = bigint_ptr(op2);
1168 if (op1->digit_count == 1 && op2->digit_count == 1) {
1169 dest->data.digit = op1_digits[0] / op2_digits[0];
1170 dest->digit_count = 1;
1171 dest->is_negative = op1->is_negative != op2->is_negative;
1172 bigint_normalize(dest);
1173 return;
1174 }
1175 if (op2->digit_count == 1 && op2_digits[0] == 1) {
1176 // X / 1 == X
1177 bigint_init_bigint(dest, op1);
1178 dest->is_negative = op1->is_negative != op2->is_negative;
1179 bigint_normalize(dest);
1180 return;
1181 }
1182
1183 const BigInt *op1_positive;
1184 BigInt op1_positive_data;
1185 if (op1->is_negative) {
1186 bigint_negate(&op1_positive_data, op1);
1187 op1_positive = &op1_positive_data;
1188 } else {
1189 op1_positive = op1;
1190 }
1191
1192 const BigInt *op2_positive;
1193 BigInt op2_positive_data;
1194 if (op2->is_negative) {
1195 bigint_negate(&op2_positive_data, op2);
1196 op2_positive = &op2_positive_data;
1197 } else {
1198 op2_positive = op2;
1199 }
1200
1201 bigint_unsigned_division(op1_positive, op2_positive, dest, nullptr);
1202 dest->is_negative = op1->is_negative != op2->is_negative;
1203 bigint_normalize(dest);
1204}
1205
1206void bigint_div_floor(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1207 if (op1->is_negative != op2->is_negative) {
1208 bigint_div_trunc(dest, op1, op2);
1209 BigInt mult_again = {0};
1210 bigint_mul(&mult_again, dest, op2);
1211 mult_again.is_negative = op1->is_negative;
1212 if (bigint_cmp(&mult_again, op1) != CmpEQ) {
1213 BigInt tmp = {0};
1214 bigint_init_bigint(&tmp, dest);
1215 BigInt neg_one = {0};
1216 bigint_init_signed(&neg_one, -1);
1217 bigint_add(dest, &tmp, &neg_one);
1218 }
1219 bigint_normalize(dest);
1220 } else {
1221 bigint_div_trunc(dest, op1, op2);
1222 }
1223}
1224
1225void bigint_rem(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1226 assert(op2->digit_count != 0); // division by zero
1227 if (op1->digit_count == 0) {
1228 bigint_init_unsigned(dest, 0);
1229 return;
1230 }
1231 const uint64_t *op1_digits = bigint_ptr(op1);
1232 const uint64_t *op2_digits = bigint_ptr(op2);
1233
1234 if (op1->digit_count == 1 && op2->digit_count == 1) {
1235 dest->data.digit = op1_digits[0] % op2_digits[0];
1236 dest->digit_count = 1;
1237 dest->is_negative = op1->is_negative;
1238 bigint_normalize(dest);
1239 return;
1240 }
1241 if (op2->digit_count == 2 && op2_digits[0] == 0 && op2_digits[1] == 1) {
1242 // special case this divisor
1243 bigint_init_unsigned(dest, op1_digits[0]);
1244 dest->is_negative = op1->is_negative;
1245 bigint_normalize(dest);
1246 return;
1247 }
1248
1249 if (op2->digit_count == 1 && op2_digits[0] == 1) {
1250 // X % 1 == 0
1251 bigint_init_unsigned(dest, 0);
1252 return;
1253 }
1254
1255 const BigInt *op1_positive;
1256 BigInt op1_positive_data;
1257 if (op1->is_negative) {
1258 bigint_negate(&op1_positive_data, op1);
1259 op1_positive = &op1_positive_data;
1260 } else {
1261 op1_positive = op1;
1262 }
1263
1264 const BigInt *op2_positive;
1265 BigInt op2_positive_data;
1266 if (op2->is_negative) {
1267 bigint_negate(&op2_positive_data, op2);
1268 op2_positive = &op2_positive_data;
1269 } else {
1270 op2_positive = op2;
1271 }
1272
1273 bigint_unsigned_division(op1_positive, op2_positive, nullptr, dest);
1274 dest->is_negative = op1->is_negative;
1275 bigint_normalize(dest);
1276}
1277
1278void bigint_mod(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1279 if (op1->is_negative) {
1280 BigInt first_rem;
1281 bigint_rem(&first_rem, op1, op2);
1282 first_rem.is_negative = !op2->is_negative;
1283 BigInt op2_minus_rem;
1284 bigint_add(&op2_minus_rem, op2, &first_rem);
1285 bigint_rem(dest, &op2_minus_rem, op2);
1286 dest->is_negative = false;
1287 } else {
1288 bigint_rem(dest, op1, op2);
1289 dest->is_negative = false;
1290 }
1291}
1292
1293void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1294 if (op1->digit_count == 0) {
1295 return bigint_init_bigint(dest, op2);
1296 }
1297 if (op2->digit_count == 0) {
1298 return bigint_init_bigint(dest, op1);
1299 }
1300 if (op1->is_negative || op2->is_negative) {
1301 size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
1302
1303 BigInt twos_comp_op1 = {0};
1304 to_twos_complement(&twos_comp_op1, op1, big_bit_count);
1305
1306 BigInt twos_comp_op2 = {0};
1307 to_twos_complement(&twos_comp_op2, op2, big_bit_count);
1308
1309 BigInt twos_comp_dest = {0};
1310 bigint_or(&twos_comp_dest, &twos_comp_op1, &twos_comp_op2);
1311
1312 from_twos_complement(dest, &twos_comp_dest, big_bit_count, true);
1313 } else {
1314 dest->is_negative = false;
1315 const uint64_t *op1_digits = bigint_ptr(op1);
1316 const uint64_t *op2_digits = bigint_ptr(op2);
1317 if (op1->digit_count == 1 && op2->digit_count == 1) {
1318 dest->digit_count = 1;
1319 dest->data.digit = op1_digits[0] | op2_digits[0];
1320 bigint_normalize(dest);
1321 return;
1322 }
1323 dest->digit_count = max(op1->digit_count, op2->digit_count);
1324 dest->data.digits = heap::c_allocator.allocate_nonzero<uint64_t>(dest->digit_count);
1325 for (size_t i = 0; i < dest->digit_count; i += 1) {
1326 uint64_t digit = 0;
1327 if (i < op1->digit_count) {
1328 digit |= op1_digits[i];
1329 }
1330 if (i < op2->digit_count) {
1331 digit |= op2_digits[i];
1332 }
1333 dest->data.digits[i] = digit;
1334 }
1335 bigint_normalize(dest);
1336 }
1337}
1338
1339void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1340 if (op1->digit_count == 0 || op2->digit_count == 0) {
1341 return bigint_init_unsigned(dest, 0);
1342 }
1343 if (op1->is_negative || op2->is_negative) {
1344 size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
1345
1346 BigInt twos_comp_op1 = {0};
1347 to_twos_complement(&twos_comp_op1, op1, big_bit_count);
1348
1349 BigInt twos_comp_op2 = {0};
1350 to_twos_complement(&twos_comp_op2, op2, big_bit_count);
1351
1352 BigInt twos_comp_dest = {0};
1353 bigint_and(&twos_comp_dest, &twos_comp_op1, &twos_comp_op2);
1354
1355 from_twos_complement(dest, &twos_comp_dest, big_bit_count, true);
1356 } else {
1357 dest->is_negative = false;
1358 const uint64_t *op1_digits = bigint_ptr(op1);
1359 const uint64_t *op2_digits = bigint_ptr(op2);
1360 if (op1->digit_count == 1 && op2->digit_count == 1) {
1361 dest->digit_count = 1;
1362 dest->data.digit = op1_digits[0] & op2_digits[0];
1363 bigint_normalize(dest);
1364 return;
1365 }
1366
1367 dest->digit_count = max(op1->digit_count, op2->digit_count);
1368 dest->data.digits = heap::c_allocator.allocate_nonzero<uint64_t>(dest->digit_count);
1369
1370 size_t i = 0;
1371 for (; i < op1->digit_count && i < op2->digit_count; i += 1) {
1372 dest->data.digits[i] = op1_digits[i] & op2_digits[i];
1373 }
1374 for (; i < dest->digit_count; i += 1) {
1375 dest->data.digits[i] = 0;
1376 }
1377 bigint_normalize(dest);
1378 }
1379}
1380
1381void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1382 if (op1->digit_count == 0) {
1383 return bigint_init_bigint(dest, op2);
1384 }
1385 if (op2->digit_count == 0) {
1386 return bigint_init_bigint(dest, op1);
1387 }
1388 if (op1->is_negative || op2->is_negative) {
1389 size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
1390
1391 BigInt twos_comp_op1 = {0};
1392 to_twos_complement(&twos_comp_op1, op1, big_bit_count);
1393
1394 BigInt twos_comp_op2 = {0};
1395 to_twos_complement(&twos_comp_op2, op2, big_bit_count);
1396
1397 BigInt twos_comp_dest = {0};
1398 bigint_xor(&twos_comp_dest, &twos_comp_op1, &twos_comp_op2);
1399
1400 from_twos_complement(dest, &twos_comp_dest, big_bit_count, true);
1401 } else {
1402 dest->is_negative = false;
1403 const uint64_t *op1_digits = bigint_ptr(op1);
1404 const uint64_t *op2_digits = bigint_ptr(op2);
1405
1406 assert(op1->digit_count > 0 && op2->digit_count > 0);
1407 if (op1->digit_count == 1 && op2->digit_count == 1) {
1408 dest->digit_count = 1;
1409 dest->data.digit = op1_digits[0] ^ op2_digits[0];
1410 bigint_normalize(dest);
1411 return;
1412 }
1413 dest->digit_count = max(op1->digit_count, op2->digit_count);
1414 dest->data.digits = heap::c_allocator.allocate_nonzero<uint64_t>(dest->digit_count);
1415 size_t i = 0;
1416 for (; i < op1->digit_count && i < op2->digit_count; i += 1) {
1417 dest->data.digits[i] = op1_digits[i] ^ op2_digits[i];
1418 }
1419 for (; i < dest->digit_count; i += 1) {
1420 if (i < op1->digit_count) {
1421 dest->data.digits[i] = op1_digits[i];
1422 } else if (i < op2->digit_count) {
1423 dest->data.digits[i] = op2_digits[i];
1424 } else {
1425 zig_unreachable();
1426 }
1427 }
1428 bigint_normalize(dest);
1429 }
1430}
1431
1432void bigint_shl(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1433 assert(!op2->is_negative);
1434
1435 if (op2->digit_count == 0) {
1436 bigint_init_bigint(dest, op1);
1437 return;
1438 }
1439
1440 if (op1->digit_count == 0) {
1441 bigint_init_unsigned(dest, 0);
1442 return;
1443 }
1444
1445 if (op2->digit_count != 1) {
1446 zig_panic("TODO shift left by amount greater than 64 bit integer");
1447 }
1448
1449 const uint64_t *op1_digits = bigint_ptr(op1);
1450 uint64_t shift_amt = bigint_as_unsigned(op2);
1451
1452 if (op1->digit_count == 1 && shift_amt < 64) {
1453 dest->data.digit = op1_digits[0] << shift_amt;
1454 if (dest->data.digit >> shift_amt == op1_digits[0]) {
1455 dest->digit_count = 1;
1456 dest->is_negative = op1->is_negative;
1457 return;
1458 }
1459 }
1460
1461 uint64_t digit_shift_count = shift_amt / 64;
1462 uint64_t leftover_shift_count = shift_amt % 64;
1463
1464 dest->data.digits = heap::c_allocator.allocate<uint64_t>(op1->digit_count + digit_shift_count + 1);
1465 dest->digit_count = digit_shift_count;
1466 uint64_t carry = 0;
1467 for (size_t i = 0; i < op1->digit_count; i += 1) {
1468 uint64_t digit = op1_digits[i];
1469 dest->data.digits[dest->digit_count] = carry | (digit << leftover_shift_count);
1470 dest->digit_count += 1;
1471 if (leftover_shift_count > 0) {
1472 carry = digit >> (64 - leftover_shift_count);
1473 } else {
1474 carry = 0;
1475 }
1476 }
1477 dest->data.digits[dest->digit_count] = carry;
1478 dest->digit_count += 1;
1479 dest->is_negative = op1->is_negative;
1480 bigint_normalize(dest);
1481}
1482
1483void bigint_shl_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed) {
1484 BigInt unwrapped = {0};
1485 bigint_shl(&unwrapped, op1, op2);
1486 bigint_truncate(dest, &unwrapped, bit_count, is_signed);
1487}
1488
1489void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1490 assert(!op2->is_negative);
1491
1492 if (op1->digit_count == 0) {
1493 return bigint_init_unsigned(dest, 0);
1494 }
1495
1496 if (op2->digit_count == 0) {
1497 return bigint_init_bigint(dest, op1);
1498 }
1499
1500 if (op2->digit_count != 1) {
1501 zig_panic("TODO shift right by amount greater than 64 bit integer");
1502 }
1503
1504 const uint64_t *op1_digits = bigint_ptr(op1);
1505 uint64_t shift_amt = bigint_as_unsigned(op2);
1506
1507 if (op1->digit_count == 1) {
1508 dest->data.digit = (shift_amt < 64) ? op1_digits[0] >> shift_amt : 0;
1509 dest->digit_count = 1;
1510 dest->is_negative = op1->is_negative;
1511 bigint_normalize(dest);
1512 return;
1513 }
1514
1515 size_t digit_shift_count = shift_amt / 64;
1516 size_t leftover_shift_count = shift_amt % 64;
1517
1518 if (digit_shift_count >= op1->digit_count) {
1519 return bigint_init_unsigned(dest, 0);
1520 }
1521
1522 dest->digit_count = op1->digit_count - digit_shift_count;
1523 uint64_t *digits;
1524 if (dest->digit_count == 1) {
1525 digits = &dest->data.digit;
1526 } else {
1527 digits = heap::c_allocator.allocate<uint64_t>(dest->digit_count);
1528 dest->data.digits = digits;
1529 }
1530
1531 uint64_t carry = 0;
1532 for (size_t op_digit_index = op1->digit_count - 1;;) {
1533 uint64_t digit = op1_digits[op_digit_index];
1534 size_t dest_digit_index = op_digit_index - digit_shift_count;
1535 digits[dest_digit_index] = carry | (digit >> leftover_shift_count);
1536 carry = (leftover_shift_count != 0) ? (digit << (64 - leftover_shift_count)) : 0;
1537
1538 if (dest_digit_index == 0) { break; }
1539 op_digit_index -= 1;
1540 }
1541 dest->is_negative = op1->is_negative;
1542 bigint_normalize(dest);
1543}
1544
1545void bigint_negate(BigInt *dest, const BigInt *op) {
1546 bigint_init_bigint(dest, op);
1547 dest->is_negative = !dest->is_negative;
1548 bigint_normalize(dest);
1549}
1550
1551void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed) {
1552 BigInt zero;
1553 bigint_init_unsigned(&zero, 0);
1554 bigint_sub_wrap(dest, &zero, op, bit_count, is_signed);
1555}
1556
1557void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed) {
1558 if (bit_count == 0) {
1559 bigint_init_unsigned(dest, 0);
1560 return;
1561 }
1562
1563 if (is_signed) {
1564 BigInt twos_comp = {0};
1565 to_twos_complement(&twos_comp, op, bit_count);
1566
1567 BigInt inverted = {0};
1568 bigint_not(&inverted, &twos_comp, bit_count, false);
1569
1570 from_twos_complement(dest, &inverted, bit_count, true);
1571 return;
1572 }
1573
1574 assert(!op->is_negative);
1575
1576 dest->is_negative = false;
1577 const uint64_t *op_digits = bigint_ptr(op);
1578 if (bit_count <= 64) {
1579 dest->digit_count = 1;
1580 if (op->digit_count == 0) {
1581 if (bit_count == 64) {
1582 dest->data.digit = UINT64_MAX;
1583 } else {
1584 dest->data.digit = (1ULL << bit_count) - 1;
1585 }
1586 } else if (op->digit_count == 1) {
1587 dest->data.digit = ~op_digits[0];
1588 if (bit_count != 64) {
1589 uint64_t mask = (1ULL << bit_count) - 1;
1590 dest->data.digit &= mask;
1591 }
1592 }
1593 bigint_normalize(dest);
1594 return;
1595 }
1596 dest->digit_count = (bit_count + 63) / 64;
1597 assert(dest->digit_count >= op->digit_count);
1598 dest->data.digits = heap::c_allocator.allocate_nonzero<uint64_t>(dest->digit_count);
1599 size_t i = 0;
1600 for (; i < op->digit_count; i += 1) {
1601 dest->data.digits[i] = ~op_digits[i];
1602 }
1603 for (; i < dest->digit_count; i += 1) {
1604 dest->data.digits[i] = 0xffffffffffffffffULL;
1605 }
1606 size_t digit_index = dest->digit_count - 1;
1607 size_t digit_bit_index = bit_count % 64;
1608 if (digit_bit_index != 0) {
1609 uint64_t mask = (1ULL << digit_bit_index) - 1;
1610 dest->data.digits[digit_index] &= mask;
1611 }
1612 bigint_normalize(dest);
1613}
1614
1615void bigint_truncate(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed) {
1616 BigInt twos_comp;
1617 to_twos_complement(&twos_comp, op, bit_count);
1618 from_twos_complement(dest, &twos_comp, bit_count, is_signed);
1619}
1620
1621Cmp bigint_cmp(const BigInt *op1, const BigInt *op2) {
1622 if (op1->is_negative && !op2->is_negative) {
1623 return CmpLT;
1624 } else if (!op1->is_negative && op2->is_negative) {
1625 return CmpGT;
1626 } else if (op1->digit_count > op2->digit_count) {
1627 return op1->is_negative ? CmpLT : CmpGT;
1628 } else if (op2->digit_count > op1->digit_count) {
1629 return op1->is_negative ? CmpGT : CmpLT;
1630 } else if (op1->digit_count == 0) {
1631 return CmpEQ;
1632 }
1633 const uint64_t *op1_digits = bigint_ptr(op1);
1634 const uint64_t *op2_digits = bigint_ptr(op2);
1635 for (size_t i = op1->digit_count - 1; ;) {
1636 uint64_t op1_digit = op1_digits[i];
1637 uint64_t op2_digit = op2_digits[i];
1638
1639 if (op1_digit > op2_digit) {
1640 return op1->is_negative ? CmpLT : CmpGT;
1641 }
1642 if (op1_digit < op2_digit) {
1643 return op1->is_negative ? CmpGT : CmpLT;
1644 }
1645
1646 if (i == 0) {
1647 return CmpEQ;
1648 }
1649 i -= 1;
1650 }
1651}
1652
1653void bigint_append_buf(Buf *buf, const BigInt *op, uint64_t base) {
1654 if (op->digit_count == 0) {
1655 buf_append_char(buf, '0');
1656 return;
1657 }
1658 if (op->is_negative) {
1659 buf_append_char(buf, '-');
1660 }
1661 if (op->digit_count == 1 && base == 10) {
1662 buf_appendf(buf, "%" ZIG_PRI_u64, op->data.digit);
1663 return;
1664 }
1665 if (op->digit_count == 1 && base == 16) {
1666 buf_appendf(buf, "%" ZIG_PRI_x64, op->data.digit);
1667 return;
1668 }
1669 size_t first_digit_index = buf_len(buf);
1670
1671 BigInt digit_bi = {0};
1672 BigInt a1 = {0};
1673 BigInt a2 = {0};
1674
1675 BigInt *a = &a1;
1676 BigInt *other_a = &a2;
1677 bigint_init_bigint(a, op);
1678
1679 BigInt base_bi = {0};
1680 bigint_init_unsigned(&base_bi, base);
1681
1682 for (;;) {
1683 bigint_rem(&digit_bi, a, &base_bi);
1684 uint8_t digit = bigint_as_unsigned(&digit_bi);
1685 buf_append_char(buf, digit_to_char(digit, false));
1686 bigint_div_trunc(other_a, a, &base_bi);
1687 {
1688 BigInt *tmp = a;
1689 a = other_a;
1690 other_a = tmp;
1691 }
1692 if (bigint_cmp_zero(a) == CmpEQ) {
1693 break;
1694 }
1695 }
1696
1697 // reverse
1698 for (size_t i = first_digit_index; i < buf_len(buf) / 2; i += 1) {
1699 size_t other_i = buf_len(buf) + first_digit_index - i - 1;
1700 uint8_t tmp = buf_ptr(buf)[i];
1701 buf_ptr(buf)[i] = buf_ptr(buf)[other_i];
1702 buf_ptr(buf)[other_i] = tmp;
1703 }
1704}
1705
1706size_t bigint_popcount_unsigned(const BigInt *bi) {
1707 assert(!bi->is_negative);
1708 if (bi->digit_count == 0)
1709 return 0;
1710
1711 size_t count = 0;
1712 size_t bit_count = bi->digit_count * 64;
1713 for (size_t i = 0; i < bit_count; i += 1) {
1714 if (bit_at_index(bi, i))
1715 count += 1;
1716 }
1717 return count;
1718}
1719
1720size_t bigint_popcount_signed(const BigInt *bi, size_t bit_count) {
1721 if (bit_count == 0)
1722 return 0;
1723 if (bi->digit_count == 0)
1724 return 0;
1725
1726 BigInt twos_comp = {0};
1727 to_twos_complement(&twos_comp, bi, bit_count);
1728
1729 size_t count = 0;
1730 for (size_t i = 0; i < bit_count; i += 1) {
1731 if (bit_at_index(&twos_comp, i))
1732 count += 1;
1733 }
1734 return count;
1735}
1736
1737size_t bigint_ctz(const BigInt *bi, size_t bit_count) {
1738 if (bit_count == 0)
1739 return 0;
1740 if (bi->digit_count == 0)
1741 return bit_count;
1742
1743 BigInt twos_comp = {0};
1744 to_twos_complement(&twos_comp, bi, bit_count);
1745
1746 size_t count = 0;
1747 for (size_t i = 0; i < bit_count; i += 1) {
1748 if (bit_at_index(&twos_comp, i))
1749 return count;
1750 count += 1;
1751 }
1752 return count;
1753}
1754
1755size_t bigint_clz(const BigInt *bi, size_t bit_count) {
1756 if (bi->is_negative || bit_count == 0)
1757 return 0;
1758 if (bi->digit_count == 0)
1759 return bit_count;
1760
1761 size_t count = 0;
1762 for (size_t i = bit_count - 1;;) {
1763 if (bit_at_index(bi, i))
1764 return count;
1765 count += 1;
1766
1767 if (i == 0) break;
1768 i -= 1;
1769 }
1770 return count;
1771}
1772
1773static uint64_t bigint_as_unsigned(const BigInt *bigint) {
1774 assert(!bigint->is_negative);
1775 if (bigint->digit_count == 0) {
1776 return 0;
1777 } else if (bigint->digit_count == 1) {
1778 return bigint->data.digit;
1779 } else {
1780 zig_unreachable();
1781 }
1782}
1783
1784uint64_t bigint_as_u64(const BigInt *bigint)
1785{
1786 return bigint_as_unsigned(bigint);
1787}
1788
1789uint32_t bigint_as_u32(const BigInt *bigint) {
1790 uint64_t value64 = bigint_as_unsigned(bigint);
1791 uint32_t value32 = (uint32_t)value64;
1792 assert (value64 == value32);
1793 return value32;
1794}
1795
1796uint8_t bigint_as_u8(const BigInt *bigint) {
1797 uint64_t value64 = bigint_as_unsigned(bigint);
1798 uint8_t value8 = (uint8_t)value64;
1799 assert (value64 == value8);
1800 return value8;
1801}
1802
1803size_t bigint_as_usize(const BigInt *bigint) {
1804 uint64_t value64 = bigint_as_unsigned(bigint);
1805 size_t valueUsize = (size_t)value64;
1806 assert (value64 == valueUsize);
1807 return valueUsize;
1808}
1809
1810int64_t bigint_as_signed(const BigInt *bigint) {
1811 if (bigint->digit_count == 0) {
1812 return 0;
1813 } else if (bigint->digit_count == 1) {
1814 if (bigint->is_negative) {
1815 if (bigint->data.digit <= 9223372036854775808ULL) {
1816 return (-((int64_t)(bigint->data.digit - 1))) - 1;
1817 } else {
1818 zig_unreachable();
1819 }
1820 } else {
1821 return bigint->data.digit;
1822 }
1823 } else {
1824 zig_unreachable();
1825 }
1826}
1827
1828Cmp bigint_cmp_zero(const BigInt *op) {
1829 if (op->digit_count == 0) {
1830 return CmpEQ;
1831 }
1832 return op->is_negative ? CmpLT : CmpGT;
1833}
1834
1835uint32_t bigint_hash(BigInt const *x) {
1836 if (x->digit_count == 0) {
1837 return 0;
1838 } else {
1839 return bigint_ptr(x)[0];
1840 }
1841}
1842
1843bool bigint_eql(BigInt const *a, BigInt const *b) {
1844 return bigint_cmp(a, b) == CmpEQ;
1845}
1846
1847void bigint_incr(BigInt *x) {
1848 if (x->digit_count == 0) {
1849 bigint_init_unsigned(x, 1);
1850 return;
1851 }
1852
1853 if (x->digit_count == 1) {
1854 if (x->is_negative && x->data.digit != 0) {
1855 x->data.digit -= 1;
1856 return;
1857 } else if (!x->is_negative && x->data.digit != UINT64_MAX) {
1858 x->data.digit += 1;
1859 return;
1860 }
1861 }
1862
1863 BigInt copy;
1864 bigint_init_bigint(&copy, x);
1865
1866 BigInt one;
1867 bigint_init_unsigned(&one, 1);
1868
1869 bigint_add(x, &copy, &one);
1870}
1871
1872void bigint_decr(BigInt *x) {
1873 if (x->digit_count == 0) {
1874 bigint_init_signed(x, -1);
1875 return;
1876 }
1877
1878 if (x->digit_count == 1) {
1879 if (x->is_negative && x->data.digit != UINT64_MAX) {
1880 x->data.digit += 1;
1881 return;
1882 } else if (!x->is_negative && x->data.digit != 0) {
1883 x->data.digit -= 1;
1884 return;
1885 }
1886 }
1887
1888 BigInt copy;
1889 bigint_init_bigint(&copy, x);
1890
1891 BigInt neg_one;
1892 bigint_init_signed(&neg_one, -1);
1893
1894 bigint_add(x, &copy, &neg_one);
1895}
src/stage1/bigint.hpp deleted-112
...@@ -1,112 +0,0 @@
1/*
2 * Copyright (c) 2017 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_BIGINT_HPP
9#define ZIG_BIGINT_HPP
10
11#include <stdint.h>
12#include <stddef.h>
13
14struct BigInt {
15 size_t digit_count;
16 union {
17 uint64_t digit;
18 uint64_t *digits; // Least significant digit first
19 } data;
20 bool is_negative;
21};
22
23struct Buf;
24struct BigFloat;
25
26enum Cmp {
27 CmpLT,
28 CmpGT,
29 CmpEQ,
30};
31
32void bigint_init_unsigned(BigInt *dest, uint64_t x);
33void bigint_init_signed(BigInt *dest, int64_t x);
34void bigint_init_bigint(BigInt *dest, const BigInt *src);
35void bigint_init_bigfloat(BigInt *dest, const BigFloat *op);
36void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative);
37void bigint_deinit(BigInt *bi);
38
39// panics if number won't fit
40uint64_t bigint_as_u64(const BigInt *bigint);
41uint32_t bigint_as_u32(const BigInt *bigint);
42uint8_t bigint_as_u8(const BigInt *bigint);
43size_t bigint_as_usize(const BigInt *bigint);
44
45int64_t bigint_as_signed(const BigInt *bigint);
46
47static inline const uint64_t *bigint_ptr(const BigInt *bigint) {
48 if (bigint->digit_count == 1) {
49 return &bigint->data.digit;
50 } else {
51 return bigint->data.digits;
52 }
53}
54
55bool bigint_fits_in_bits(const BigInt *bn, size_t bit_count, bool is_signed);
56void bigint_write_twos_complement(const BigInt *big_int, uint8_t *buf, size_t bit_count, bool is_big_endian);
57void bigint_read_twos_complement(BigInt *dest, const uint8_t *buf, size_t bit_count, bool is_big_endian,
58 bool is_signed);
59void bigint_max(BigInt* dest, const BigInt *op1, const BigInt *op2);
60void bigint_min(BigInt* dest, const BigInt *op1, const BigInt *op2);
61void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2);
62void bigint_add_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed);
63void bigint_sub(BigInt *dest, const BigInt *op1, const BigInt *op2);
64void bigint_sub_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed);
65void bigint_mul(BigInt *dest, const BigInt *op1, const BigInt *op2);
66void bigint_mul_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed);
67void bigint_div_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2);
68void bigint_div_floor(BigInt *dest, const BigInt *op1, const BigInt *op2);
69void bigint_rem(BigInt *dest, const BigInt *op1, const BigInt *op2);
70void bigint_mod(BigInt *dest, const BigInt *op1, const BigInt *op2);
71
72void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2);
73void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2);
74void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2);
75
76void bigint_shl(BigInt *dest, const BigInt *op1, const BigInt *op2);
77void bigint_shl_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed);
78void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2);
79
80void bigint_negate(BigInt *dest, const BigInt *op);
81void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed);
82void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed);
83void bigint_truncate(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed);
84
85Cmp bigint_cmp(const BigInt *op1, const BigInt *op2);
86
87void bigint_append_buf(Buf *buf, const BigInt *op, uint64_t base);
88
89size_t bigint_ctz(const BigInt *bi, size_t bit_count);
90size_t bigint_clz(const BigInt *bi, size_t bit_count);
91size_t bigint_popcount_signed(const BigInt *bi, size_t bit_count);
92size_t bigint_popcount_unsigned(const BigInt *bi);
93
94size_t bigint_bits_needed(const BigInt *op);
95
96
97// convenience functions
98Cmp bigint_cmp_zero(const BigInt *op);
99
100void bigint_incr(BigInt *value);
101void bigint_decr(BigInt *value);
102
103bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result);
104
105uint32_t bigint_hash(BigInt const *x);
106bool bigint_eql(BigInt const *a, BigInt const *b);
107
108void bigint_add_sat(BigInt* dest, const BigInt *op1, const BigInt *op2, uint32_t bit_count, bool is_signed);
109void bigint_sub_sat(BigInt* dest, const BigInt *op1, const BigInt *op2, uint32_t bit_count, bool is_signed);
110void bigint_mul_sat(BigInt* dest, const BigInt *op1, const BigInt *op2, uint32_t bit_count, bool is_signed);
111void bigint_shl_sat(BigInt* dest, const BigInt *op1, const BigInt *op2, uint32_t bit_count, bool is_signed);
112#endif
src/stage1/buffer.cpp deleted-79
...@@ -1,79 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "buffer.hpp"
9#include <stdarg.h>
10#include <stdlib.h>
11#include <stdio.h>
12
13Buf *buf_vprintf(const char *format, va_list ap) {
14 va_list ap2;
15 va_copy(ap2, ap);
16
17 int len1 = vsnprintf(nullptr, 0, format, ap);
18 assert(len1 >= 0);
19
20 size_t required_size = len1 + 1;
21
22 Buf *buf = buf_alloc_fixed(len1);
23
24 int len2 = vsnprintf(buf_ptr(buf), required_size, format, ap2);
25 assert(len2 == len1);
26
27 va_end(ap2);
28
29 return buf;
30}
31
32Buf *buf_sprintf(const char *format, ...) {
33 va_list ap;
34 va_start(ap, format);
35 Buf *result = buf_vprintf(format, ap);
36 va_end(ap);
37 return result;
38}
39
40void buf_appendf(Buf *buf, const char *format, ...) {
41 assert(buf->list.length);
42 va_list ap, ap2;
43 va_start(ap, format);
44 va_copy(ap2, ap);
45
46 int len1 = vsnprintf(nullptr, 0, format, ap);
47 assert(len1 >= 0);
48
49 size_t required_size = len1 + 1;
50
51 size_t orig_len = buf_len(buf);
52
53 buf_resize(buf, orig_len + len1);
54
55 int len2 = vsnprintf(buf_ptr(buf) + orig_len, required_size, format, ap2);
56 assert(len2 == len1);
57
58 va_end(ap2);
59 va_end(ap);
60}
61
62// these functions are not static inline so they can be better used as template parameters
63bool buf_eql_buf(Buf *buf, Buf *other) {
64 return buf_eql_mem(buf, buf_ptr(other), buf_len(other));
65}
66
67uint32_t buf_hash(Buf *buf) {
68 assert(buf->list.length);
69 size_t interval = buf->list.length / 256;
70 if (interval == 0)
71 interval = 1;
72 // FNV 32-bit hash
73 uint32_t h = 2166136261;
74 for (size_t i = 0; i < buf_len(buf); i += interval) {
75 h = h ^ ((uint8_t)buf->list.at(i));
76 h = h * 16777619;
77 }
78 return h;
79}
src/stage1/buffer.hpp deleted-211
...@@ -1,211 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_BUFFER_HPP
9#define ZIG_BUFFER_HPP
10
11#include "list.hpp"
12
13#include <stdint.h>
14#include <ctype.h>
15#include <stdarg.h>
16
17#define BUF_INIT {{0}}
18
19// Note, you must call one of the alloc, init, or resize functions to have an
20// initialized buffer. The assertions should help with this.
21struct Buf {
22 ZigList<char> list;
23};
24
25Buf *buf_sprintf(const char *format, ...)
26 ATTRIBUTE_PRINTF(1, 2);
27Buf *buf_vprintf(const char *format, va_list ap);
28
29static inline size_t buf_len(const Buf *buf) {
30 assert(buf);
31 assert(buf->list.length);
32 return buf->list.length - 1;
33}
34
35static inline char *buf_ptr(Buf *buf) {
36 assert(buf);
37 assert(buf->list.length);
38 return buf->list.items;
39}
40
41static inline const char *buf_ptr(const Buf *buf) {
42 assert(buf);
43 assert(buf->list.length);
44 return buf->list.items;
45}
46
47static inline void buf_resize(Buf *buf, size_t new_len) {
48 buf->list.resize(new_len + 1);
49 buf->list.at(buf_len(buf)) = 0;
50}
51
52static inline Buf *buf_alloc_fixed(size_t size) {
53 Buf *buf = heap::c_allocator.create<Buf>();
54 buf_resize(buf, size);
55 return buf;
56}
57
58static inline Buf *buf_alloc(void) {
59 return buf_alloc_fixed(0);
60}
61
62static inline void buf_deinit(Buf *buf) {
63 buf->list.deinit();
64}
65
66static inline void buf_destroy(Buf *buf) {
67 buf_deinit(buf);
68 heap::c_allocator.destroy(buf);
69}
70
71static inline void buf_init_from_mem(Buf *buf, const char *ptr, size_t len) {
72 assert(len != SIZE_MAX);
73 buf->list.resize(len + 1);
74 memcpy(buf_ptr(buf), ptr, len);
75 buf->list.at(buf_len(buf)) = 0;
76}
77
78static inline void buf_init_from_str(Buf *buf, const char *str) {
79 buf_init_from_mem(buf, str, strlen(str));
80}
81
82static inline void buf_init_from_buf(Buf *buf, Buf *other) {
83 buf_init_from_mem(buf, buf_ptr(other), buf_len(other));
84}
85
86static inline Buf *buf_create_from_mem(const char *ptr, size_t len) {
87 assert(len != SIZE_MAX);
88 Buf *buf = heap::c_allocator.create<Buf>();
89 buf_init_from_mem(buf, ptr, len);
90 return buf;
91}
92
93static inline Buf *buf_create_from_slice(Slice<uint8_t> slice) {
94 return buf_create_from_mem((const char *)slice.ptr, slice.len);
95}
96
97static inline Buf *buf_create_from_str(const char *str) {
98 return buf_create_from_mem(str, strlen(str));
99}
100
101static inline Buf *buf_create_from_buf(Buf *buf) {
102 return buf_create_from_mem(buf_ptr(buf), buf_len(buf));
103}
104
105static inline Buf *buf_slice(Buf *in_buf, size_t start, size_t end) {
106 assert(in_buf->list.length);
107 assert(start != SIZE_MAX);
108 assert(end != SIZE_MAX);
109 assert(start < buf_len(in_buf));
110 assert(end <= buf_len(in_buf));
111 Buf *out_buf = heap::c_allocator.create<Buf>();
112 out_buf->list.resize(end - start + 1);
113 memcpy(buf_ptr(out_buf), buf_ptr(in_buf) + start, end - start);
114 out_buf->list.at(buf_len(out_buf)) = 0;
115 return out_buf;
116}
117
118static inline void buf_append_mem(Buf *buf, const char *mem, size_t mem_len) {
119 assert(buf->list.length);
120 assert(mem_len != SIZE_MAX);
121 size_t old_len = buf_len(buf);
122 buf_resize(buf, old_len + mem_len);
123 memcpy(buf_ptr(buf) + old_len, mem, mem_len);
124 buf->list.at(buf_len(buf)) = 0;
125}
126
127static inline void buf_append_str(Buf *buf, const char *str) {
128 assert(buf->list.length);
129 buf_append_mem(buf, str, strlen(str));
130}
131
132static inline void buf_append_buf(Buf *buf, Buf *append_buf) {
133 assert(buf->list.length);
134 buf_append_mem(buf, buf_ptr(append_buf), buf_len(append_buf));
135}
136
137static inline void buf_append_char(Buf *buf, uint8_t c) {
138 assert(buf->list.length);
139 buf_append_mem(buf, (const char *)&c, 1);
140}
141
142void buf_appendf(Buf *buf, const char *format, ...)
143 ATTRIBUTE_PRINTF(2, 3);
144
145static inline bool buf_eql_mem(Buf *buf, const char *mem, size_t mem_len) {
146 assert(buf->list.length);
147 return mem_eql_mem(buf_ptr(buf), buf_len(buf), mem, mem_len);
148}
149
150static inline bool buf_eql_mem_ignore_case(Buf *buf, const char *mem, size_t mem_len) {
151 assert(buf->list.length);
152 return mem_eql_mem_ignore_case(buf_ptr(buf), buf_len(buf), mem, mem_len);
153}
154
155static inline bool buf_eql_str(Buf *buf, const char *str) {
156 assert(buf->list.length);
157 return buf_eql_mem(buf, str, strlen(str));
158}
159
160static inline bool buf_eql_str_ignore_case(Buf *buf, const char *str) {
161 assert(buf->list.length);
162 return buf_eql_mem_ignore_case(buf, str, strlen(str));
163}
164
165static inline bool buf_starts_with_mem(Buf *buf, const char *mem, size_t mem_len) {
166 if (buf_len(buf) < mem_len) {
167 return false;
168 }
169 return memcmp(buf_ptr(buf), mem, mem_len) == 0;
170}
171
172static inline bool buf_starts_with_buf(Buf *buf, Buf *sub) {
173 return buf_starts_with_mem(buf, buf_ptr(sub), buf_len(sub));
174}
175
176static inline bool buf_starts_with_str(Buf *buf, const char *str) {
177 return buf_starts_with_mem(buf, str, strlen(str));
178}
179
180static inline bool buf_ends_with_mem(Buf *buf, const char *mem, size_t mem_len) {
181 return mem_ends_with_mem(buf_ptr(buf), buf_len(buf), mem, mem_len);
182}
183
184static inline bool buf_ends_with_str(Buf *buf, const char *str) {
185 return buf_ends_with_mem(buf, str, strlen(str));
186}
187
188bool buf_eql_buf(Buf *buf, Buf *other);
189uint32_t buf_hash(Buf *buf);
190
191static inline void buf_upcase(Buf *buf) {
192 for (size_t i = 0; i < buf_len(buf); i += 1) {
193 buf_ptr(buf)[i] = (char)toupper(buf_ptr(buf)[i]);
194 }
195}
196
197static inline Slice<uint8_t> buf_to_slice(Buf *buf) {
198 return Slice<uint8_t>{reinterpret_cast<uint8_t*>(buf_ptr(buf)), buf_len(buf)};
199}
200
201static inline void buf_replace(Buf* buf, char from, char to) {
202 const size_t count = buf_len(buf);
203 char* ptr = buf_ptr(buf);
204 for (size_t i = 0; i < count; ++i) {
205 char& l = ptr[i];
206 if (l == from)
207 l = to;
208 }
209}
210
211#endif
src/stage1/codegen.cpp deleted-11034
...@@ -1,11034 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "analyze.hpp"
9#include "codegen.hpp"
10#include "errmsg.hpp"
11#include "error.hpp"
12#include "hash_map.hpp"
13#include "ir.hpp"
14#include "os.hpp"
15#include "target.hpp"
16#include "util.hpp"
17#include "zig_llvm.h"
18#include "stage2.h"
19#include "softfloat.hpp"
20#include "zigendian.h"
21
22#include <stdio.h>
23#include <string.h>
24#include <errno.h>
25#include <math.h>
26
27enum ResumeId {
28 ResumeIdManual,
29 ResumeIdReturn,
30 ResumeIdCall,
31};
32
33static ZigPackage *new_package(const char *root_src_dir, const char *root_src_path, const char *pkg_path) {
34 ZigPackage *entry = heap::c_allocator.create<ZigPackage>();
35 entry->package_table.init(4);
36 buf_init_from_str(&entry->root_src_dir, root_src_dir);
37 buf_init_from_str(&entry->root_src_path, root_src_path);
38 buf_init_from_str(&entry->pkg_path, pkg_path);
39 return entry;
40}
41
42ZigPackage *new_anonymous_package() {
43 return new_package("", "", "");
44}
45
46static const char *symbols_that_llvm_depends_on[] = {
47 "memcpy",
48 "memset",
49 "sqrt",
50 "powi",
51 "sin",
52 "cos",
53 "pow",
54 "exp",
55 "exp2",
56 "log",
57 "log10",
58 "log2",
59 "fma",
60 "fmaf",
61 "fmal",
62 "fmaq",
63 "fabs",
64 "minnum",
65 "maxnum",
66 "copysign",
67 "floor",
68 "ceil",
69 "trunc",
70 "rint",
71 "nearbyint",
72 "round",
73 // TODO probably all of compiler-rt needs to go here
74};
75
76void codegen_set_strip(CodeGen *g, bool strip) {
77 g->strip_debug_symbols = strip;
78 if (!target_has_debug_info(g->zig_target)) {
79 g->strip_debug_symbols = true;
80 }
81}
82
83static LLVMValueRef get_soft_float_fn(CodeGen *g, const char *name, int param_count, LLVMTypeRef param_type, LLVMTypeRef return_type);
84static void render_const_val(CodeGen *g, ZigValue *const_val, const char *name);
85static void render_const_val_global(CodeGen *g, ZigValue *const_val, const char *name);
86static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *name);
87static void generate_error_name_table(CodeGen *g);
88static bool value_is_all_undef(CodeGen *g, ZigValue *const_val);
89static void gen_undef_init(CodeGen *g, ZigType *ptr_type, ZigType *value_type, LLVMValueRef ptr);
90static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment);
91static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_instr,
92 LLVMTypeRef target_frame_struct_llvm_ty, LLVMValueRef target_frame_ptr,
93 ZigType *result_type, ZigType *ptr_result_type, LLVMValueRef result_loc, bool non_async);
94
95static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {
96 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
97 assert(kind_id != 0);
98 LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(LLVMGetGlobalContext(), kind_id, 0);
99 LLVMAddAttributeAtIndex(val, attr_index, llvm_attr);
100}
101
102static void addLLVMAttrStr(LLVMValueRef val, LLVMAttributeIndex attr_index,
103 const char *attr_name, const char *attr_val)
104{
105 LLVMAttributeRef llvm_attr = LLVMCreateStringAttribute(LLVMGetGlobalContext(),
106 attr_name, (unsigned)strlen(attr_name), attr_val, (unsigned)strlen(attr_val));
107 LLVMAddAttributeAtIndex(val, attr_index, llvm_attr);
108}
109
110static void addLLVMAttrInt(LLVMValueRef val, LLVMAttributeIndex attr_index,
111 const char *attr_name, uint64_t attr_val)
112{
113 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
114 assert(kind_id != 0);
115 LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(LLVMGetGlobalContext(), kind_id, attr_val);
116 LLVMAddAttributeAtIndex(val, attr_index, llvm_attr);
117}
118
119static void addLLVMFnAttr(LLVMValueRef fn_val, const char *attr_name) {
120 return addLLVMAttr(fn_val, -1, attr_name);
121}
122
123static void addLLVMFnAttrStr(LLVMValueRef fn_val, const char *attr_name, const char *attr_val) {
124 return addLLVMAttrStr(fn_val, -1, attr_name, attr_val);
125}
126
127static void addLLVMFnAttrInt(LLVMValueRef fn_val, const char *attr_name, uint64_t attr_val) {
128 return addLLVMAttrInt(fn_val, -1, attr_name, attr_val);
129}
130
131static void addLLVMArgAttr(LLVMValueRef fn_val, unsigned param_index, const char *attr_name) {
132 return addLLVMAttr(fn_val, param_index + 1, attr_name);
133}
134
135static void addLLVMArgAttrInt(LLVMValueRef fn_val, unsigned param_index, const char *attr_name, uint64_t attr_val) {
136 return addLLVMAttrInt(fn_val, param_index + 1, attr_name, attr_val);
137}
138
139static bool is_symbol_available(CodeGen *g, const char *name) {
140 Buf *buf_name = buf_create_from_str(name);
141 bool result =
142 g->exported_symbol_names.maybe_get(buf_name) == nullptr &&
143 g->external_symbol_names.maybe_get(buf_name) == nullptr;
144 buf_destroy(buf_name);
145 return result;
146}
147
148static const char *get_mangled_name(CodeGen *g, const char *original_name) {
149 if (is_symbol_available(g, original_name))
150 return original_name;
151
152 int n = 0;
153 for (;; n += 1) {
154 const char *new_name = buf_ptr(buf_sprintf("%s.%d", original_name, n));
155 if (is_symbol_available(g, new_name)) {
156 return new_name;
157 }
158 }
159}
160
161// Sync this with emit_error_unless_callconv_allowed_for_target in analyze.cpp
162static ZigLLVM_CallingConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
163 switch (cc) {
164 case CallingConventionUnspecified:
165 case CallingConventionInline:
166 return ZigLLVM_Fast;
167 case CallingConventionC:
168 return ZigLLVM_C;
169 case CallingConventionNaked:
170 zig_unreachable();
171 case CallingConventionStdcall:
172 assert(g->zig_target->arch == ZigLLVM_x86);
173 return ZigLLVM_X86_StdCall;
174 case CallingConventionFastcall:
175 assert(g->zig_target->arch == ZigLLVM_x86);
176 return ZigLLVM_X86_FastCall;
177 case CallingConventionVectorcall:
178 if (g->zig_target->arch == ZigLLVM_x86)
179 return ZigLLVM_X86_VectorCall;
180 if (target_is_arm(g->zig_target) &&
181 target_arch_pointer_bit_width(g->zig_target->arch) == 64)
182 return ZigLLVM_AArch64_VectorCall;
183 zig_unreachable();
184 case CallingConventionThiscall:
185 assert(g->zig_target->arch == ZigLLVM_x86);
186 return ZigLLVM_X86_ThisCall;
187 case CallingConventionAsync:
188 return ZigLLVM_Fast;
189 case CallingConventionAPCS:
190 assert(target_is_arm(g->zig_target));
191 return ZigLLVM_ARM_APCS;
192 case CallingConventionAAPCS:
193 assert(target_is_arm(g->zig_target));
194 return ZigLLVM_ARM_AAPCS;
195 case CallingConventionAAPCSVFP:
196 assert(target_is_arm(g->zig_target));
197 return ZigLLVM_ARM_AAPCS_VFP;
198 case CallingConventionInterrupt:
199 if (g->zig_target->arch == ZigLLVM_x86 ||
200 g->zig_target->arch == ZigLLVM_x86_64)
201 return ZigLLVM_X86_INTR;
202 if (g->zig_target->arch == ZigLLVM_avr)
203 return ZigLLVM_AVR_INTR;
204 if (g->zig_target->arch == ZigLLVM_msp430)
205 return ZigLLVM_MSP430_INTR;
206 zig_unreachable();
207 case CallingConventionSignal:
208 assert(g->zig_target->arch == ZigLLVM_avr);
209 return ZigLLVM_AVR_SIGNAL;
210 case CallingConventionSysV:
211 assert(g->zig_target->arch == ZigLLVM_x86_64);
212 return ZigLLVM_X86_64_SysV;
213 case CallingConventionWin64:
214 assert(g->zig_target->arch == ZigLLVM_x86_64);
215 return ZigLLVM_Win64;
216 case CallingConventionPtxKernel:
217 assert(g->zig_target->arch == ZigLLVM_nvptx ||
218 g->zig_target->arch == ZigLLVM_nvptx64);
219 return ZigLLVM_PTX_Kernel;
220 case CallingConventionAmdgpuKernel:
221 assert(g->zig_target->arch == ZigLLVM_amdgcn);
222 return ZigLLVM_AMDGPU_KERNEL;
223
224 }
225 zig_unreachable();
226}
227
228static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {
229 if (g->unwind_tables) {
230 addLLVMFnAttrInt(fn_val, "uwtable", 2);
231 }
232}
233
234static LLVMLinkage to_llvm_linkage(GlobalLinkageId id, bool is_extern) {
235 switch (id) {
236 case GlobalLinkageIdInternal:
237 return LLVMInternalLinkage;
238 case GlobalLinkageIdStrong:
239 return LLVMExternalLinkage;
240 case GlobalLinkageIdWeak:
241 if (is_extern) return LLVMExternalWeakLinkage;
242 return LLVMWeakODRLinkage;
243 case GlobalLinkageIdLinkOnce:
244 return LLVMLinkOnceODRLinkage;
245 }
246 zig_unreachable();
247}
248
249struct CalcLLVMFieldIndex {
250 uint32_t offset;
251 uint32_t field_index;
252};
253
254static void calc_llvm_field_index_add(CodeGen *g, CalcLLVMFieldIndex *calc, ZigType *ty) {
255 if (!type_has_bits(g, ty)) return;
256 uint32_t ty_align = get_abi_alignment(g, ty);
257
258 if (calc->offset % ty_align != 0) {
259 uint32_t llvm_align = LLVMABIAlignmentOfType(g->target_data_ref, get_llvm_type(g, ty));
260
261 // Alignment according to Zig.
262 uint32_t adj_offset = calc->offset + (ty_align - (calc->offset % ty_align));
263 // Alignment according to LLVM.
264 uint32_t adj_llvm_offset = (calc->offset % llvm_align) ?
265 calc->offset + (llvm_align - (calc->offset % llvm_align)) :
266 calc->offset;
267 // Cannot under-align structure fields.
268 assert(adj_offset >= adj_llvm_offset);
269
270 // Zig will insert an extra padding field here.
271 if (adj_offset != adj_llvm_offset)
272 calc->field_index += 1;
273
274 calc->offset = adj_offset;
275 }
276 calc->offset += ty->abi_size;
277 calc->field_index += 1;
278}
279
280// label (grep this): [fn_frame_struct_layout]
281static void frame_index_trace_arg_calc(CodeGen *g, CalcLLVMFieldIndex *calc, ZigType *return_type) {
282 calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // function pointer
283 calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // resume index
284 calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // awaiter index
285
286 if (type_has_bits(g, return_type)) {
287 calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // *ReturnType (callee's)
288 calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // *ReturnType (awaiter's)
289 calc_llvm_field_index_add(g, calc, return_type); // ReturnType
290 }
291}
292
293static uint32_t frame_index_trace_arg(CodeGen *g, ZigType *return_type) {
294 CalcLLVMFieldIndex calc = {0};
295 frame_index_trace_arg_calc(g, &calc, return_type);
296 return calc.field_index;
297}
298
299// label (grep this): [fn_frame_struct_layout]
300static void frame_index_arg_calc(CodeGen *g, CalcLLVMFieldIndex *calc, ZigType *return_type) {
301 frame_index_trace_arg_calc(g, calc, return_type);
302
303 if (codegen_fn_has_err_ret_tracing_arg(g, return_type)) {
304 calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // *StackTrace (callee's)
305 calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // *StackTrace (awaiter's)
306 }
307}
308
309// label (grep this): [fn_frame_struct_layout]
310static uint32_t frame_index_trace_stack(CodeGen *g, ZigFn *fn) {
311 size_t field_index = 6;
312 bool have_stack_trace = codegen_fn_has_err_ret_tracing_arg(g, fn->type_entry->data.fn.fn_type_id.return_type);
313 if (have_stack_trace) {
314 field_index += 2;
315 }
316 field_index += fn->type_entry->data.fn.fn_type_id.param_count;
317 ZigType *locals_struct = fn->frame_type->data.frame.locals_struct;
318 TypeStructField *field = locals_struct->data.structure.fields[field_index];
319 return field->gen_index;
320}
321
322
323static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {
324 if (!g->have_err_ret_tracing) {
325 return UINT32_MAX;
326 }
327 if (fn_is_async(fn_table_entry)) {
328 return UINT32_MAX;
329 }
330 ZigType *fn_type = fn_table_entry->type_entry;
331 if (!fn_type_can_fail(&fn_type->data.fn.fn_type_id)) {
332 return UINT32_MAX;
333 }
334 ZigType *return_type = fn_type->data.fn.fn_type_id.return_type;
335 bool first_arg_ret = type_has_bits(g, return_type) && handle_is_ptr(g, return_type);
336 return first_arg_ret ? 1 : 0;
337}
338
339static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {
340 if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows && g->dll_export_fns) {
341 LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass);
342 }
343}
344
345static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {
346 if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows) {
347 // TODO come up with a good explanation/understanding for why we never do
348 // DLLImportStorageClass. Empirically it only causes problems. But let's have
349 // this documented and then clean up the code accordingly.
350 //LLVMSetDLLStorageClass(global_value, LLVMDLLImportStorageClass);
351 }
352}
353
354static bool cc_want_sret_attr(CallingConvention cc) {
355 switch (cc) {
356 case CallingConventionNaked:
357 zig_unreachable();
358 case CallingConventionC:
359 case CallingConventionInterrupt:
360 case CallingConventionSignal:
361 case CallingConventionStdcall:
362 case CallingConventionFastcall:
363 case CallingConventionVectorcall:
364 case CallingConventionThiscall:
365 case CallingConventionAPCS:
366 case CallingConventionAAPCS:
367 case CallingConventionAAPCSVFP:
368 case CallingConventionSysV:
369 case CallingConventionWin64:
370 case CallingConventionPtxKernel:
371 case CallingConventionAmdgpuKernel:
372 return true;
373 case CallingConventionAsync:
374 case CallingConventionUnspecified:
375 case CallingConventionInline:
376 return false;
377 }
378 zig_unreachable();
379}
380
381static void add_common_fn_attributes(CodeGen *g, LLVMValueRef llvm_fn) {
382 if (!g->red_zone) {
383 addLLVMFnAttr(llvm_fn, "noredzone");
384 }
385
386 addLLVMFnAttr(llvm_fn, "nounwind");
387 add_uwtable_attr(g, llvm_fn);
388 addLLVMFnAttr(llvm_fn, "nobuiltin");
389
390 if (g->build_mode == BuildModeSmallRelease) {
391 // Optimize for small code size.
392 addLLVMFnAttr(llvm_fn, "minsize");
393 addLLVMFnAttr(llvm_fn, "optsize");
394 }
395
396 if (g->zig_target->llvm_cpu_name != nullptr) {
397 ZigLLVMAddFunctionAttr(llvm_fn, "target-cpu", g->zig_target->llvm_cpu_name);
398 }
399 if (g->zig_target->llvm_cpu_features != nullptr) {
400 ZigLLVMAddFunctionAttr(llvm_fn, "target-features", g->zig_target->llvm_cpu_features);
401 }
402}
403
404static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
405 const char *unmangled_name = buf_ptr(&fn->symbol_name);
406 const char *symbol_name;
407 GlobalLinkageId linkage;
408 if (fn->body_node == nullptr) {
409 symbol_name = unmangled_name;
410 linkage = GlobalLinkageIdStrong;
411 } else if (fn->export_list.length == 0) {
412 symbol_name = get_mangled_name(g, unmangled_name);
413 linkage = GlobalLinkageIdInternal;
414 } else {
415 GlobalExport *fn_export = &fn->export_list.items[0];
416 symbol_name = buf_ptr(&fn_export->name);
417 linkage = fn_export->linkage;
418 }
419
420 CallingConvention cc = fn->type_entry->data.fn.fn_type_id.cc;
421 bool is_async = fn_is_async(fn);
422
423 ZigType *fn_type = fn->type_entry;
424 // Make the raw_type_ref populated
425 resolve_llvm_types_fn(g, fn);
426 LLVMTypeRef fn_llvm_type = fn->raw_type_ref;
427 LLVMValueRef llvm_fn = nullptr;
428 if (fn->body_node == nullptr) {
429 assert(fn->proto_node->type == NodeTypeFnProto);
430 AstNodeFnProto *fn_proto = &fn->proto_node->data.fn_proto;
431
432 const unsigned fn_addrspace = ZigLLVMDataLayoutGetProgramAddressSpace(g->target_data_ref);
433
434 // The compiler tries to deduplicate extern definitions by looking up
435 // their name, this was introduced to allow the declaration of the same
436 // extern function with differing prototypes.
437 // When Wasm is targeted this check becomes a problem as the user may
438 // declare two (or more) extern functions sharing the same name but
439 // imported from different modules!
440 // To overcome this problem we generate a mangled identifier out of the
441 // import and the function name, this name is only visible within the
442 // compiler as we're telling LLVM (using 'wasm-import-name' and
443 // 'wasm-import-name') what the real function name is and where to find
444 // it.
445 bool use_mangled_name = target_is_wasm(g->zig_target) &&
446 fn_proto->is_extern && fn_proto->lib_name != nullptr;
447 // This is subtle but important to match libc symbols at static link time correctly.
448 // We treat "c" lib_name as a special library indicating that it should be defined
449 // in libc. But if we mangle a libc symbol name here with "c" module name, then wasm-ld cannot resolve
450 // the symbol. This is because at the static link time with wasm-ld, the linker does not
451 // take module names into account, and instead looking for a pure symbol name (i.e. function name)
452 // written into the ".linking" custom section (i.e. it does not use import section).
453 // This is the intended behavior of wasm-ld, because Wasm has a concept of host functions,
454 // which are undefined functions supposed to be resolved by host runtimes *with module names*
455 // at load times even if it is "static linked" with the linker.
456 use_mangled_name = use_mangled_name && (strcmp(buf_ptr(fn_proto->lib_name), "c") != 0);
457 // Pick a weird name to avoid collisions...
458 // This whole function should be burned to the ground.
459 Buf *mangled_symbol_buf = use_mangled_name ?
460 buf_sprintf("%s|%s", unmangled_name, buf_ptr(fn_proto->lib_name)) :
461 nullptr;
462 symbol_name = use_mangled_name ?
463 buf_ptr(mangled_symbol_buf) : unmangled_name;
464
465 LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, symbol_name);
466
467 if (existing_llvm_fn) {
468 if (mangled_symbol_buf) buf_destroy(mangled_symbol_buf);
469 return LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, fn_addrspace));
470 } else {
471 Buf *buf_symbol_name = buf_create_from_str(symbol_name);
472 auto entry = g->exported_symbol_names.maybe_get(buf_symbol_name);
473 buf_destroy(buf_symbol_name);
474
475 if (entry == nullptr) {
476 llvm_fn = LLVMAddFunction(g->module, symbol_name, fn_llvm_type);
477
478 if (use_mangled_name) {
479 // Note that "wasm-import-module"ed symbols will not be resolved
480 // in the future version of wasm-ld since the attribute basically means that
481 // "the symbol should be resolved at load time by runtimes", though
482 // the symbol is already mangled here and it is written into "linking" section
483 // used by wasm-ld to match symbols, so it should not be expected by users.
484 // tl;dr is that users should not put the lib_name specifier on extern statements
485 // if they want to link symbols with wasm-ld.
486 addLLVMFnAttrStr(llvm_fn, "wasm-import-name", unmangled_name);
487 addLLVMFnAttrStr(llvm_fn, "wasm-import-module", buf_ptr(fn_proto->lib_name));
488 }
489 } else {
490 assert(entry->value->id == TldIdFn);
491 TldFn *tld_fn = reinterpret_cast<TldFn *>(entry->value);
492 // Make the raw_type_ref populated
493 resolve_llvm_types_fn(g, tld_fn->fn_entry);
494 tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, symbol_name,
495 tld_fn->fn_entry->raw_type_ref);
496 llvm_fn = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, LLVMPointerType(fn_llvm_type, fn_addrspace));
497 if (mangled_symbol_buf) buf_destroy(mangled_symbol_buf);
498 return llvm_fn;
499 }
500
501 if (mangled_symbol_buf) buf_destroy(mangled_symbol_buf);
502 }
503 } else {
504 llvm_fn = LLVMAddFunction(g->module, symbol_name, fn_llvm_type);
505
506 for (size_t i = 1; i < fn->export_list.length; i += 1) {
507 GlobalExport *fn_export = &fn->export_list.items[i];
508 LLVMAddAlias2(g->module, LLVMTypeOf(llvm_fn), 0, llvm_fn, buf_ptr(&fn_export->name));
509 }
510 }
511
512 if (cc == CallingConventionInline)
513 addLLVMFnAttr(llvm_fn, "alwaysinline");
514
515 if (fn->is_noinline || (cc != CallingConventionInline && fn->alignstack_value != 0))
516 addLLVMFnAttr(llvm_fn, "noinline");
517
518 if (cc == CallingConventionNaked) {
519 addLLVMFnAttr(llvm_fn, "naked");
520 } else {
521 ZigLLVMFunctionSetCallingConv(llvm_fn, get_llvm_cc(g, cc));
522 }
523
524 if (g->tsan_enabled) {
525 addLLVMFnAttr(llvm_fn, "sanitize_thread");
526 }
527
528 bool want_cold = fn->is_cold;
529 if (want_cold) {
530 ZigLLVMAddFunctionAttrCold(llvm_fn);
531 }
532
533
534 LLVMSetLinkage(llvm_fn, to_llvm_linkage(linkage, fn->body_node == nullptr));
535
536 if (linkage == GlobalLinkageIdInternal) {
537 LLVMSetUnnamedAddr(llvm_fn, true);
538 }
539
540 ZigType *return_type = fn_type->data.fn.fn_type_id.return_type;
541 if (return_type->id == ZigTypeIdUnreachable) {
542 addLLVMFnAttr(llvm_fn, "noreturn");
543 }
544
545 if (!calling_convention_allows_zig_types(cc)) {
546 // A simplistic and desperate attempt at making the compiler respect the
547 // target ABI for return types.
548 // This is just enough to avoid miscompiling the test suite, it will be
549 // better in stage2.
550 ZigType *int_type = return_type->id == ZigTypeIdInt ? return_type :
551 return_type->id == ZigTypeIdEnum ? return_type->data.enumeration.tag_int_type :
552 nullptr;
553
554 if (int_type != nullptr) {
555 const bool is_signed = int_type->data.integral.is_signed;
556 const uint32_t bit_width = int_type->data.integral.bit_count;
557 bool should_extend = false;
558
559 // Rough equivalent of Clang's isPromotableIntegerType.
560 switch (bit_width) {
561 case 1: // bool
562 case 8: // {un,}signed char
563 case 16: // {un,}signed short
564 should_extend = true;
565 break;
566 default:
567 break;
568 }
569
570 switch (g->zig_target->arch) {
571 case ZigLLVM_sparcv9:
572 case ZigLLVM_riscv64:
573 case ZigLLVM_ppc64:
574 case ZigLLVM_ppc64le:
575 // Always extend to the register width.
576 should_extend = bit_width < 64;
577 break;
578 default:
579 break;
580 }
581
582 // {zero,sign}-extend the result.
583 if (should_extend) {
584 if (is_signed)
585 addLLVMAttr(llvm_fn, 0, "signext");
586 else
587 addLLVMAttr(llvm_fn, 0, "zeroext");
588 }
589 }
590 }
591
592 if (fn->body_node != nullptr) {
593 maybe_export_dll(g, llvm_fn, linkage);
594
595 bool want_ssp_attrs = g->build_mode != BuildModeFastRelease &&
596 g->build_mode != BuildModeSmallRelease &&
597 g->link_libc &&
598 // WASI-libc does not support stack-protector yet.
599 !target_is_wasm(g->zig_target);
600 if (want_ssp_attrs) {
601 addLLVMFnAttr(llvm_fn, "sspstrong");
602 addLLVMFnAttrStr(llvm_fn, "stack-protector-buffer-size", "4");
603 }
604 if (g->have_stack_probing && !fn->def_scope->safety_off) {
605 addLLVMFnAttrStr(llvm_fn, "probe-stack", "__zig_probe_stack");
606 } else if (g->zig_target->os == OsUefi) {
607 addLLVMFnAttrStr(llvm_fn, "no-stack-arg-probe", "");
608 }
609 } else {
610 maybe_import_dll(g, llvm_fn, linkage);
611 }
612
613 if (fn->alignstack_value != 0) {
614 addLLVMFnAttrInt(llvm_fn, "alignstack", fn->alignstack_value);
615 }
616
617 if (!g->omit_frame_pointer && cc != CallingConventionInline) {
618 ZigLLVMAddFunctionAttr(llvm_fn, "frame-pointer", "all");
619 }
620 if (fn->section_name) {
621 LLVMSetSection(llvm_fn, buf_ptr(fn->section_name));
622 }
623 if (fn->align_bytes > 0) {
624 LLVMSetAlignment(llvm_fn, (unsigned)fn->align_bytes);
625 } else {
626 // We'd like to set the best alignment for the function here, but on Darwin LLVM gives
627 // "Cannot getTypeInfo() on a type that is unsized!" assertion failure when calling
628 // any of the functions for getting alignment. Not specifying the alignment should
629 // use the ABI alignment, which is fine.
630 }
631
632 add_common_fn_attributes(g, llvm_fn);
633
634 if (is_async) {
635 addLLVMArgAttr(llvm_fn, 0, "nonnull");
636 } else {
637 unsigned init_gen_i = 0;
638 if (!type_has_bits(g, return_type)) {
639 // nothing to do
640 } else if (type_is_nonnull_ptr(g, return_type)) {
641 addLLVMAttr(llvm_fn, 0, "nonnull");
642 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
643 // Sret pointers must not be address 0
644 addLLVMArgAttr(llvm_fn, 0, "nonnull");
645 ZigLLVMAddSretAttr(llvm_fn, get_llvm_type(g, return_type));
646 if (cc_want_sret_attr(cc)) {
647 addLLVMArgAttr(llvm_fn, 0, "noalias");
648 }
649 init_gen_i = 1;
650 }
651
652 // set parameter attributes
653 FnWalk fn_walk = {};
654 fn_walk.id = FnWalkIdAttrs;
655 fn_walk.data.attrs.fn = fn;
656 fn_walk.data.attrs.llvm_fn = llvm_fn;
657 fn_walk.data.attrs.gen_i = init_gen_i;
658 walk_function_params(g, fn_type, &fn_walk);
659
660 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn);
661 if (err_ret_trace_arg_index != UINT32_MAX) {
662 // Error return trace memory is in the stack, which is impossible to be at address 0
663 // on any architecture.
664 addLLVMArgAttr(llvm_fn, (unsigned)err_ret_trace_arg_index, "nonnull");
665 }
666 }
667
668 return llvm_fn;
669}
670
671static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn) {
672 if (fn->llvm_value)
673 return fn->llvm_value;
674
675 fn->llvm_value = make_fn_llvm_value(g, fn);
676 fn->llvm_name = strdup(LLVMGetValueName(fn->llvm_value));
677 return fn->llvm_value;
678}
679
680static uint32_t node_line_onebased(AstNode *node) {
681 RootStruct *root_struct = node->owner->data.structure.root_struct;
682 assert(node->main_token < root_struct->token_count);
683 return root_struct->token_locs[node->main_token].line + 1;
684}
685
686static uint32_t node_column_onebased(AstNode *node) {
687 RootStruct *root_struct = node->owner->data.structure.root_struct;
688 assert(node->main_token < root_struct->token_count);
689 return root_struct->token_locs[node->main_token].column + 1;
690}
691
692static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
693 if (scope->di_scope)
694 return scope->di_scope;
695
696 ZigType *import = get_scope_import(scope);
697 switch (scope->id) {
698 case ScopeIdCImport:
699 zig_unreachable();
700 case ScopeIdFnDef:
701 {
702 assert(scope->parent);
703 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
704 ZigFn *fn_table_entry = fn_scope->fn_entry;
705 if (!fn_table_entry->proto_node)
706 return get_di_scope(g, scope->parent);
707 unsigned line_number = node_line_onebased(fn_table_entry->proto_node);
708 unsigned scope_line = line_number;
709 bool is_definition = fn_table_entry->body_node != nullptr;
710 bool is_optimized = g->build_mode != BuildModeDebug;
711 bool is_internal_linkage = (fn_table_entry->body_node != nullptr &&
712 fn_table_entry->export_list.length == 0);
713 unsigned flags = ZigLLVM_DIFlags_StaticMember;
714 ZigLLVMDIScope *fn_di_scope = get_di_scope(g, scope->parent);
715 assert(fn_di_scope != nullptr);
716 assert(fn_table_entry->raw_di_type != nullptr);
717 ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,
718 fn_di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
719 import->data.structure.root_struct->di_file, line_number,
720 fn_table_entry->raw_di_type, is_internal_linkage,
721 is_definition, scope_line, flags, is_optimized, nullptr);
722
723 scope->di_scope = ZigLLVMSubprogramToScope(subprogram);
724 if (!g->strip_debug_symbols) {
725 ZigLLVMFnSetSubprogram(fn_llvm_value(g, fn_table_entry), subprogram);
726 }
727 return scope->di_scope;
728 }
729 case ScopeIdDecls:
730 if (scope->parent) {
731 ScopeDecls *decls_scope = (ScopeDecls *)scope;
732 assert(decls_scope->container_type);
733 scope->di_scope = ZigLLVMTypeToScope(get_llvm_di_type(g, decls_scope->container_type));
734 } else {
735 scope->di_scope = ZigLLVMFileToScope(import->data.structure.root_struct->di_file);
736 }
737 return scope->di_scope;
738 case ScopeIdBlock:
739 case ScopeIdDefer:
740 {
741 assert(scope->parent);
742 ZigLLVMDILexicalBlock *di_block = ZigLLVMCreateLexicalBlock(g->dbuilder,
743 get_di_scope(g, scope->parent),
744 import->data.structure.root_struct->di_file,
745 node_line_onebased(scope->source_node),
746 node_column_onebased(scope->source_node));
747 scope->di_scope = ZigLLVMLexicalBlockToScope(di_block);
748 return scope->di_scope;
749 }
750 case ScopeIdVarDecl:
751 case ScopeIdDeferExpr:
752 case ScopeIdLoop:
753 case ScopeIdSuspend:
754 case ScopeIdCompTime:
755 case ScopeIdNoSuspend:
756 case ScopeIdRuntime:
757 case ScopeIdTypeOf:
758 case ScopeIdExpr:
759 return get_di_scope(g, scope->parent);
760 }
761 zig_unreachable();
762}
763
764static void clear_debug_source_node(CodeGen *g) {
765 ZigLLVMClearCurrentDebugLocation(g->builder);
766}
767
768static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, ZigType *operand_type,
769 const char *signed_name, const char *unsigned_name)
770{
771 ZigType *int_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
772 char fn_name[64];
773
774 assert(int_type->id == ZigTypeIdInt);
775 const char *signed_str = int_type->data.integral.is_signed ? signed_name : unsigned_name;
776
777 LLVMTypeRef param_types[] = {
778 get_llvm_type(g, operand_type),
779 get_llvm_type(g, operand_type),
780 };
781
782 if (operand_type->id == ZigTypeIdVector) {
783 snprintf(fn_name, sizeof(fn_name), "llvm.%s.with.overflow.v%" PRIu64 "i%" PRIu32, signed_str,
784 operand_type->data.vector.len, int_type->data.integral.bit_count);
785
786 LLVMTypeRef return_elem_types[] = {
787 get_llvm_type(g, operand_type),
788 LLVMVectorType(LLVMInt1Type(), operand_type->data.vector.len),
789 };
790 LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false);
791 LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false);
792 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type);
793 assert(LLVMGetIntrinsicID(fn_val));
794 return fn_val;
795 } else {
796 snprintf(fn_name, sizeof(fn_name), "llvm.%s.with.overflow.i%" PRIu32, signed_str, int_type->data.integral.bit_count);
797
798 LLVMTypeRef return_elem_types[] = {
799 get_llvm_type(g, operand_type),
800 LLVMInt1Type(),
801 };
802 LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false);
803 LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false);
804 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type);
805 assert(LLVMGetIntrinsicID(fn_val));
806 return fn_val;
807 }
808}
809
810static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *operand_type, AddSubMul add_sub_mul) {
811 ZigType *int_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
812 assert(int_type->id == ZigTypeIdInt);
813
814 ZigLLVMFnKey key = {};
815 key.id = ZigLLVMFnIdOverflowArithmetic;
816 key.data.overflow_arithmetic.is_signed = int_type->data.integral.is_signed;
817 key.data.overflow_arithmetic.add_sub_mul = add_sub_mul;
818 key.data.overflow_arithmetic.bit_count = (uint32_t)int_type->data.integral.bit_count;
819 key.data.overflow_arithmetic.vector_len = (operand_type->id == ZigTypeIdVector) ?
820 operand_type->data.vector.len : 0;
821
822 auto existing_entry = g->llvm_fn_table.maybe_get(key);
823 if (existing_entry)
824 return existing_entry->value;
825
826 LLVMValueRef fn_val;
827 switch (add_sub_mul) {
828 case AddSubMulAdd:
829 fn_val = get_arithmetic_overflow_fn(g, operand_type, "sadd", "uadd");
830 break;
831 case AddSubMulSub:
832 fn_val = get_arithmetic_overflow_fn(g, operand_type, "ssub", "usub");
833 break;
834 case AddSubMulMul:
835 fn_val = get_arithmetic_overflow_fn(g, operand_type, "smul", "umul");
836 break;
837 }
838
839 g->llvm_fn_table.put(key, fn_val);
840 return fn_val;
841}
842
843static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn_id, BuiltinFnId op) {
844 assert(type_entry->id == ZigTypeIdFloat ||
845 type_entry->id == ZigTypeIdVector);
846
847 bool is_vector = (type_entry->id == ZigTypeIdVector);
848 ZigType *float_type = is_vector ? type_entry->data.vector.elem_type : type_entry;
849 uint32_t float_bits = float_type->data.floating.bit_count;
850
851 // LLVM incorrectly lowers the fma builtin for f128 to fmal, which is for
852 // `long double`. On some targets this will be correct; on others it will be incorrect.
853 if (fn_id == ZigLLVMFnIdFMA && float_bits == 128 &&
854 !target_long_double_is_f128(g->zig_target))
855 {
856 LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, "fmaq");
857 if (existing_llvm_fn != nullptr) return existing_llvm_fn;
858
859 LLVMTypeRef float_type_ref = get_llvm_type(g, type_entry);
860 LLVMTypeRef return_elem_types[3] = { float_type_ref, float_type_ref, float_type_ref };
861 LLVMTypeRef fn_type = LLVMFunctionType(float_type_ref, return_elem_types, 3, false);
862 return LLVMAddFunction(g->module, "fmaq", fn_type);
863 }
864
865 ZigLLVMFnKey key = {};
866 key.id = fn_id;
867 key.data.floating.bit_count = float_bits;
868 key.data.floating.vector_len = is_vector ? (uint32_t)type_entry->data.vector.len : 0;
869 key.data.floating.op = op;
870
871 auto existing_entry = g->llvm_fn_table.maybe_get(key);
872 if (existing_entry)
873 return existing_entry->value;
874
875 const char *name;
876 uint32_t num_args;
877 if (fn_id == ZigLLVMFnIdFMA) {
878 name = "fma";
879 num_args = 3;
880 } else if (fn_id == ZigLLVMFnIdFloatOp) {
881 name = float_un_op_to_name(op);
882 num_args = 1;
883 } else {
884 zig_unreachable();
885 }
886
887 char fn_name[64];
888 if (is_vector)
889 snprintf(fn_name, sizeof(fn_name), "llvm.%s.v%" PRIu32 "f%" PRIu32, name, key.data.floating.vector_len, key.data.floating.bit_count);
890 else
891 snprintf(fn_name, sizeof(fn_name), "llvm.%s.f%" PRIu32, name, key.data.floating.bit_count);
892 LLVMTypeRef float_type_ref = get_llvm_type(g, type_entry);
893 LLVMTypeRef return_elem_types[3] = { float_type_ref, float_type_ref, float_type_ref };
894 LLVMTypeRef fn_type = LLVMFunctionType(float_type_ref, return_elem_types, num_args, false);
895 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type);
896 assert(LLVMGetIntrinsicID(fn_val));
897
898 g->llvm_fn_table.put(key, fn_val);
899 return fn_val;
900}
901
902static LLVMValueRef gen_store_untyped(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr,
903 uint32_t alignment, bool is_volatile)
904{
905 LLVMValueRef instruction = LLVMBuildStore(g->builder, value, ptr);
906 if (is_volatile) LLVMSetVolatile(instruction, true);
907 if (alignment != 0) {
908 LLVMSetAlignment(instruction, alignment);
909 }
910 return instruction;
911}
912
913static LLVMValueRef gen_store(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr, ZigType *ptr_type) {
914 assert(ptr_type->id == ZigTypeIdPointer);
915 uint32_t alignment = get_ptr_align(g, ptr_type);
916 return gen_store_untyped(g, value, ptr, alignment, ptr_type->data.pointer.is_volatile);
917}
918
919static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMTypeRef elem_llvm_ty, LLVMValueRef ptr,
920 uint32_t alignment, bool is_volatile, const char *name)
921{
922 LLVMValueRef result = LLVMBuildLoad2(g->builder, elem_llvm_ty, ptr, name);
923 if (is_volatile) LLVMSetVolatile(result, true);
924 if (alignment != 0) {
925 LLVMSetAlignment(result, alignment);
926 }
927 return result;
928}
929
930static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, const char *name) {
931 assert(ptr_type->id == ZigTypeIdPointer);
932 uint32_t alignment = get_ptr_align(g, ptr_type);
933 LLVMTypeRef elem_llvm_ty = get_llvm_type(g, ptr_type->data.pointer.child_type);
934 bool is_volatile = ptr_type->data.pointer.is_volatile;
935 return gen_load_untyped(g, elem_llvm_ty, ptr, alignment, is_volatile, name);
936}
937
938static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type, ZigType *ptr_type) {
939 if (type_has_bits(g, type)) {
940 if (handle_is_ptr(g, type)) {
941 return ptr;
942 } else {
943 assert(ptr_type->id == ZigTypeIdPointer);
944 return gen_load(g, ptr, ptr_type, "");
945 }
946 } else {
947 return nullptr;
948 }
949}
950
951static void ir_assert_impl(bool ok, Stage1AirInst *source_instruction, const char *file, unsigned int line) {
952 if (ok) return;
953 src_assert_impl(ok, source_instruction->source_node, file, line);
954}
955
956#define ir_assert(OK, SOURCE_INSTRUCTION) ir_assert_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__)
957
958static bool ir_want_fast_math(CodeGen *g, Stage1AirInst *instruction) {
959 // TODO memoize
960 Scope *scope = instruction->scope;
961 while (scope) {
962 if (scope->id == ScopeIdBlock) {
963 ScopeBlock *block_scope = (ScopeBlock *)scope;
964 if (block_scope->fast_math_set_node)
965 return block_scope->fast_math_on;
966 } else if (scope->id == ScopeIdDecls) {
967 ScopeDecls *decls_scope = (ScopeDecls *)scope;
968 if (decls_scope->fast_math_set_node)
969 return decls_scope->fast_math_on;
970 }
971 scope = scope->parent;
972 }
973 return false;
974}
975
976static bool ir_want_runtime_safety_scope(CodeGen *g, Scope *scope) {
977 // TODO memoize
978 while (scope) {
979 if (scope->id == ScopeIdBlock) {
980 ScopeBlock *block_scope = (ScopeBlock *)scope;
981 if (block_scope->safety_set_node)
982 return !block_scope->safety_off;
983 } else if (scope->id == ScopeIdDecls) {
984 ScopeDecls *decls_scope = (ScopeDecls *)scope;
985 if (decls_scope->safety_set_node)
986 return !decls_scope->safety_off;
987 }
988 scope = scope->parent;
989 }
990
991 return (g->build_mode != BuildModeFastRelease &&
992 g->build_mode != BuildModeSmallRelease);
993}
994
995static bool ir_want_runtime_safety(CodeGen *g, Stage1AirInst *instruction) {
996 return ir_want_runtime_safety_scope(g, instruction->scope);
997}
998
999static Buf *panic_msg_buf(PanicMsgId msg_id) {
1000 switch (msg_id) {
1001 case PanicMsgIdCount:
1002 zig_unreachable();
1003 case PanicMsgIdBoundsCheckFailure:
1004 return buf_create_from_str("index out of bounds");
1005 case PanicMsgIdCastNegativeToUnsigned:
1006 return buf_create_from_str("attempt to cast negative value to unsigned integer");
1007 case PanicMsgIdCastTruncatedData:
1008 return buf_create_from_str("integer cast truncated bits");
1009 case PanicMsgIdIntegerOverflow:
1010 return buf_create_from_str("integer overflow");
1011 case PanicMsgIdShlOverflowedBits:
1012 return buf_create_from_str("left shift overflowed bits");
1013 case PanicMsgIdShrOverflowedBits:
1014 return buf_create_from_str("right shift overflowed bits");
1015 case PanicMsgIdDivisionByZero:
1016 return buf_create_from_str("division by zero");
1017 case PanicMsgIdRemainderDivisionByZero:
1018 return buf_create_from_str("remainder division by zero or negative value");
1019 case PanicMsgIdExactDivisionRemainder:
1020 return buf_create_from_str("exact division produced remainder");
1021 case PanicMsgIdUnwrapOptionalFail:
1022 return buf_create_from_str("attempt to use null value");
1023 case PanicMsgIdUnreachable:
1024 return buf_create_from_str("reached unreachable code");
1025 case PanicMsgIdInvalidErrorCode:
1026 return buf_create_from_str("invalid error code");
1027 case PanicMsgIdIncorrectAlignment:
1028 return buf_create_from_str("incorrect alignment");
1029 case PanicMsgIdBadUnionField:
1030 return buf_create_from_str("access of inactive union field");
1031 case PanicMsgIdBadEnumValue:
1032 return buf_create_from_str("invalid enum value");
1033 case PanicMsgIdFloatToInt:
1034 return buf_create_from_str("integer part of floating point value out of bounds");
1035 case PanicMsgIdPtrCastNull:
1036 return buf_create_from_str("cast causes pointer to be null");
1037 case PanicMsgIdBadResume:
1038 return buf_create_from_str("resumed an async function which already returned");
1039 case PanicMsgIdBadAwait:
1040 return buf_create_from_str("async function awaited twice");
1041 case PanicMsgIdBadReturn:
1042 return buf_create_from_str("async function returned twice");
1043 case PanicMsgIdResumedAnAwaitingFn:
1044 return buf_create_from_str("awaiting function resumed");
1045 case PanicMsgIdFrameTooSmall:
1046 return buf_create_from_str("frame too small");
1047 case PanicMsgIdResumedFnPendingAwait:
1048 return buf_create_from_str("resumed an async function which can only be awaited");
1049 case PanicMsgIdBadNoSuspendCall:
1050 return buf_create_from_str("async function called in nosuspend scope suspended");
1051 case PanicMsgIdResumeNotSuspendedFn:
1052 return buf_create_from_str("resumed a non-suspended function");
1053 case PanicMsgIdBadSentinel:
1054 return buf_create_from_str("sentinel mismatch");
1055 case PanicMsgIdShxTooBigRhs:
1056 return buf_create_from_str("shift amount is greater than the type size");
1057 }
1058 zig_unreachable();
1059}
1060
1061static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
1062 ZigValue *val = &g->panic_msg_vals[msg_id];
1063 if (!val->llvm_global) {
1064
1065 Buf *buf_msg = panic_msg_buf(msg_id);
1066 ZigValue *array_val = create_const_str_lit(g, buf_msg)->data.x_ptr.data.ref.pointee;
1067 init_const_slice(g, val, array_val, 0, buf_len(buf_msg), true, nullptr);
1068
1069 render_const_val(g, val, "");
1070 render_const_val_global(g, val, "");
1071
1072 assert(val->llvm_global);
1073 }
1074
1075 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
1076 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false);
1077 ZigType *str_type = get_slice_type(g, u8_ptr_type);
1078 return LLVMConstBitCast(val->llvm_global, LLVMPointerType(get_llvm_type(g, str_type), 0));
1079}
1080
1081static ZigType *ptr_to_stack_trace_type(CodeGen *g) {
1082 return get_pointer_to_type(g, get_stack_trace_type(g), false);
1083}
1084
1085static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace_arg,
1086 bool stack_trace_is_llvm_alloca)
1087{
1088 assert(g->panic_fn != nullptr);
1089 LLVMValueRef fn_val = fn_llvm_value(g, g->panic_fn);
1090 ZigLLVM_CallingConv llvm_cc = get_llvm_cc(g, g->panic_fn->type_entry->data.fn.fn_type_id.cc);
1091 if (stack_trace_arg == nullptr) {
1092 stack_trace_arg = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type(g)));
1093 }
1094 LLVMValueRef null_ret_alloc;
1095 {
1096 ZigValue null_val = {};
1097 null_val.special = ConstValSpecialStatic;
1098 null_val.data.x_optional = nullptr;
1099 null_val.type = get_optional_type2(g, g->builtin_types.entry_usize);
1100 LLVMValueRef null_ret_val = gen_const_val(g, &null_val, "");
1101 null_ret_alloc = build_alloca(g, null_val.type, "ret_addr", 0);
1102 LLVMBuildStore(g->builder, null_ret_val, null_ret_alloc);
1103 }
1104
1105 LLVMValueRef args[] = {
1106 msg_arg,
1107 stack_trace_arg,
1108 null_ret_alloc,
1109 };
1110 ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, args, 3, llvm_cc, ZigLLVM_CallAttrAuto, "");
1111 if (!stack_trace_is_llvm_alloca) {
1112 // The stack trace argument is not in the stack of the caller, so
1113 // we'd like to set tail call here, but because slices (the type of msg_arg) are
1114 // still passed as pointers (see https://github.com/ziglang/zig/issues/561) we still
1115 // cannot make this a tail call.
1116 //LLVMSetTailCall(call_instruction, true);
1117 }
1118 LLVMBuildUnreachable(g->builder);
1119}
1120
1121// TODO update most callsites to call gen_assertion instead of this
1122static void gen_safety_crash(CodeGen *g, PanicMsgId msg_id) {
1123 gen_panic(g, get_panic_msg_ptr_val(g, msg_id), nullptr, false);
1124}
1125
1126static void gen_assertion_scope(CodeGen *g, PanicMsgId msg_id, Scope *source_scope) {
1127 if (ir_want_runtime_safety_scope(g, source_scope)) {
1128 gen_safety_crash(g, msg_id);
1129 } else {
1130 LLVMBuildUnreachable(g->builder);
1131 }
1132}
1133
1134static void gen_assertion(CodeGen *g, PanicMsgId msg_id, Stage1AirInst *source_instruction) {
1135 return gen_assertion_scope(g, msg_id, source_instruction->scope);
1136}
1137
1138static LLVMValueRef gen_wasm_memory_size(CodeGen *g) {
1139 if (g->wasm_memory_size)
1140 return g->wasm_memory_size;
1141
1142 // TODO adjust for wasm64 as well
1143 // declare i32 @llvm.wasm.memory.size.i32(i32) nounwind readonly
1144 LLVMTypeRef param_type = LLVMInt32Type();
1145 LLVMTypeRef fn_type = LLVMFunctionType(LLVMInt32Type(), &param_type, 1, false);
1146 g->wasm_memory_size = LLVMAddFunction(g->module, "llvm.wasm.memory.size.i32", fn_type);
1147 assert(LLVMGetIntrinsicID(g->wasm_memory_size));
1148
1149 return g->wasm_memory_size;
1150}
1151
1152static LLVMValueRef gen_wasm_memory_grow(CodeGen *g) {
1153 if (g->wasm_memory_grow)
1154 return g->wasm_memory_grow;
1155
1156 // TODO adjust for wasm64 as well
1157 // declare i32 @llvm.wasm.memory.grow.i32(i32, i32) nounwind
1158 LLVMTypeRef param_types[] = {
1159 LLVMInt32Type(),
1160 LLVMInt32Type(),
1161 };
1162 LLVMTypeRef fn_type = LLVMFunctionType(LLVMInt32Type(), param_types, 2, false);
1163 g->wasm_memory_grow = LLVMAddFunction(g->module, "llvm.wasm.memory.grow.i32", fn_type);
1164 assert(LLVMGetIntrinsicID(g->wasm_memory_grow));
1165
1166 return g->wasm_memory_grow;
1167}
1168
1169static LLVMValueRef gen_prefetch(CodeGen *g) {
1170 if (g->prefetch)
1171 return g->prefetch;
1172
1173 // declare void @llvm.prefetch(i8*, i32, i32, i32)
1174 LLVMTypeRef param_types[] = {
1175 LLVMPointerType(LLVMInt8Type(), 0),
1176 LLVMInt32Type(),
1177 LLVMInt32Type(),
1178 LLVMInt32Type(),
1179 };
1180 LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 4, false);
1181 g->prefetch = LLVMAddFunction(g->module, "llvm.prefetch.p0", fn_type);
1182 assert(LLVMGetIntrinsicID(g->prefetch));
1183
1184 return g->prefetch;
1185}
1186
1187static LLVMValueRef get_stacksave_fn_val(CodeGen *g) {
1188 if (g->stacksave_fn_val)
1189 return g->stacksave_fn_val;
1190
1191 // declare i8* @llvm.stacksave()
1192
1193 LLVMTypeRef fn_type = LLVMFunctionType(LLVMPointerType(LLVMInt8Type(), 0), nullptr, 0, false);
1194 g->stacksave_fn_val = LLVMAddFunction(g->module, "llvm.stacksave", fn_type);
1195 assert(LLVMGetIntrinsicID(g->stacksave_fn_val));
1196
1197 return g->stacksave_fn_val;
1198}
1199
1200static LLVMValueRef get_stackrestore_fn_val(CodeGen *g) {
1201 if (g->stackrestore_fn_val)
1202 return g->stackrestore_fn_val;
1203
1204 // declare void @llvm.stackrestore(i8* %ptr)
1205
1206 LLVMTypeRef param_type = LLVMPointerType(LLVMInt8Type(), 0);
1207 LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), &param_type, 1, false);
1208 g->stackrestore_fn_val = LLVMAddFunction(g->module, "llvm.stackrestore", fn_type);
1209 assert(LLVMGetIntrinsicID(g->stackrestore_fn_val));
1210
1211 return g->stackrestore_fn_val;
1212}
1213
1214static LLVMValueRef get_write_register_fn_val(CodeGen *g) {
1215 if (g->write_register_fn_val)
1216 return g->write_register_fn_val;
1217
1218 // declare void @llvm.write_register.i64(metadata, i64 @value)
1219 // !0 = !{!"sp\00"}
1220
1221 LLVMTypeRef param_types[] = {
1222 LLVMMetadataTypeInContext(LLVMGetGlobalContext()),
1223 LLVMIntType(g->pointer_size_bytes * 8),
1224 };
1225
1226 LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 2, false);
1227 Buf *name = buf_sprintf("llvm.write_register.i%d", g->pointer_size_bytes * 8);
1228 g->write_register_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
1229 assert(LLVMGetIntrinsicID(g->write_register_fn_val));
1230
1231 return g->write_register_fn_val;
1232}
1233
1234static LLVMValueRef get_return_address_fn_val(CodeGen *g) {
1235 if (g->return_address_fn_val)
1236 return g->return_address_fn_val;
1237
1238 ZigType *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
1239
1240 LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, return_type),
1241 &g->builtin_types.entry_i32->llvm_type, 1, false);
1242 g->return_address_fn_val = LLVMAddFunction(g->module, "llvm.returnaddress", fn_type);
1243 assert(LLVMGetIntrinsicID(g->return_address_fn_val));
1244
1245 return g->return_address_fn_val;
1246}
1247
1248static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
1249 if (g->add_error_return_trace_addr_fn_val != nullptr)
1250 return g->add_error_return_trace_addr_fn_val;
1251
1252 LLVMTypeRef arg_types[] = {
1253 get_llvm_type(g, ptr_to_stack_trace_type(g)),
1254 g->builtin_types.entry_usize->llvm_type,
1255 };
1256 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);
1257
1258 const char *fn_name = get_mangled_name(g, "__zig_add_err_ret_trace_addr");
1259 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref);
1260 addLLVMFnAttr(fn_val, "alwaysinline");
1261 LLVMSetLinkage(fn_val, LLVMInternalLinkage);
1262 ZigLLVMFunctionSetCallingConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
1263 add_common_fn_attributes(g, fn_val);
1264 // Error return trace memory is in the stack, which is impossible to be at address 0
1265 // on any architecture.
1266 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
1267 if (!g->omit_frame_pointer) {
1268 ZigLLVMAddFunctionAttr(fn_val, "frame-pointer", "all");
1269 }
1270
1271 LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry");
1272 LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder);
1273 LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder);
1274 LLVMPositionBuilderAtEnd(g->builder, entry_block);
1275 ZigLLVMClearCurrentDebugLocation(g->builder);
1276
1277 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
1278
1279 // stack_trace.instruction_addresses[stack_trace.index & (stack_trace.instruction_addresses.len - 1)] = return_address;
1280
1281 LLVMValueRef err_ret_trace_ptr = LLVMGetParam(fn_val, 0);
1282 LLVMValueRef address_value = LLVMGetParam(fn_val, 1);
1283
1284 size_t index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index;
1285 LLVMValueRef index_field_ptr = LLVMBuildStructGEP2(g->builder,
1286 get_llvm_type(g, g->stack_trace_type),
1287 err_ret_trace_ptr, (unsigned)index_field_index, "");
1288 size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index;
1289 LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP2(g->builder,
1290 get_llvm_type(g, g->stack_trace_type),
1291 err_ret_trace_ptr, (unsigned)addresses_field_index, "");
1292
1293 ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry;
1294 size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index;
1295 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder,
1296 ZigLLVMGetGEPResultElementType(addresses_field_ptr),
1297 addresses_field_ptr, (unsigned)ptr_field_index, "");
1298 size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index;
1299 LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder,
1300 ZigLLVMGetGEPResultElementType(addresses_field_ptr),
1301 addresses_field_ptr, (unsigned)len_field_index, "");
1302
1303 LLVMValueRef len_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_field_ptr),
1304 len_field_ptr, 0, false, "");
1305 LLVMValueRef index_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(index_field_ptr),
1306 index_field_ptr, 0, false, "");
1307 LLVMValueRef len_val_minus_one = LLVMBuildSub(g->builder, len_value, LLVMConstInt(usize_type_ref, 1, false), "");
1308 LLVMValueRef masked_val = LLVMBuildAnd(g->builder, index_val, len_val_minus_one, "");
1309 LLVMValueRef address_indices[] = {
1310 masked_val,
1311 };
1312
1313 LLVMValueRef ptr_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_field_ptr),
1314 ptr_field_ptr, 0, false, "");
1315 LLVMValueRef address_slot = LLVMBuildInBoundsGEP2(g->builder, usize_type_ref, ptr_value, address_indices, 1, "");
1316
1317 gen_store_untyped(g, address_value, address_slot, 0, false);
1318
1319 // stack_trace.index += 1;
1320 LLVMValueRef index_plus_one_val = LLVMBuildNUWAdd(g->builder, index_val, LLVMConstInt(usize_type_ref, 1, false), "");
1321 gen_store_untyped(g, index_plus_one_val, index_field_ptr, 0, false);
1322
1323 // return;
1324 LLVMBuildRetVoid(g->builder);
1325
1326 LLVMPositionBuilderAtEnd(g->builder, prev_block);
1327 if (!g->strip_debug_symbols) {
1328 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
1329 }
1330
1331 g->add_error_return_trace_addr_fn_val = fn_val;
1332 return fn_val;
1333}
1334
1335static LLVMValueRef get_return_err_fn(CodeGen *g) {
1336 if (g->return_err_fn != nullptr)
1337 return g->return_err_fn;
1338
1339 assert(g->err_tag_type != nullptr);
1340
1341 LLVMTypeRef arg_types[] = {
1342 // error return trace pointer
1343 get_llvm_type(g, ptr_to_stack_trace_type(g)),
1344 };
1345 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false);
1346
1347 const char *fn_name = get_mangled_name(g, "__zig_return_error");
1348 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref);
1349 addLLVMFnAttr(fn_val, "noinline"); // so that we can look at return address
1350 addLLVMFnAttr(fn_val, "cold");
1351 LLVMSetLinkage(fn_val, LLVMInternalLinkage);
1352 ZigLLVMFunctionSetCallingConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
1353 add_common_fn_attributes(g, fn_val);
1354 if (!g->omit_frame_pointer) {
1355 ZigLLVMAddFunctionAttr(fn_val, "frame-pointer", "all");
1356 }
1357
1358 // this is above the ZigLLVMClearCurrentDebugLocation
1359 LLVMValueRef add_error_return_trace_addr_fn_val = get_add_error_return_trace_addr_fn(g);
1360
1361 LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry");
1362 LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder);
1363 LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder);
1364 LLVMPositionBuilderAtEnd(g->builder, entry_block);
1365 ZigLLVMClearCurrentDebugLocation(g->builder);
1366
1367 LLVMValueRef err_ret_trace_ptr = LLVMGetParam(fn_val, 0);
1368
1369 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
1370 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, g->builtin_types.entry_i32));
1371 LLVMValueRef return_address_ptr = LLVMBuildCall2(g->builder,
1372 LLVMGlobalGetValueType(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, "");
1373 LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, return_address_ptr, usize_type_ref, "");
1374
1375 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(fn_val, "Return");
1376 LLVMBasicBlockRef dest_non_null_block = LLVMAppendBasicBlock(fn_val, "DestNonNull");
1377
1378 LLVMValueRef null_dest_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, err_ret_trace_ptr,
1379 LLVMConstNull(LLVMTypeOf(err_ret_trace_ptr)), "");
1380 LLVMBuildCondBr(g->builder, null_dest_bit, return_block, dest_non_null_block);
1381
1382 LLVMPositionBuilderAtEnd(g->builder, return_block);
1383 LLVMBuildRetVoid(g->builder);
1384
1385 LLVMPositionBuilderAtEnd(g->builder, dest_non_null_block);
1386 LLVMValueRef args[] = { err_ret_trace_ptr, return_address };
1387 ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(add_error_return_trace_addr_fn_val),
1388 add_error_return_trace_addr_fn_val, args, 2,
1389 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, "");
1390 LLVMBuildRetVoid(g->builder);
1391
1392 LLVMPositionBuilderAtEnd(g->builder, prev_block);
1393 if (!g->strip_debug_symbols) {
1394 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
1395 }
1396
1397 g->return_err_fn = fn_val;
1398 return fn_val;
1399}
1400
1401static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
1402 if (g->safety_crash_err_fn != nullptr)
1403 return g->safety_crash_err_fn;
1404
1405 static const char *unwrap_err_msg_text = "attempt to unwrap error: ";
1406
1407 g->generate_error_name_table = true;
1408 generate_error_name_table(g);
1409 assert(g->err_name_table != nullptr);
1410
1411 // Generate the constant part of the error message
1412 LLVMValueRef msg_prefix_init = LLVMConstString(unwrap_err_msg_text, strlen(unwrap_err_msg_text), 1);
1413 LLVMValueRef msg_prefix = LLVMAddGlobal(g->module, LLVMTypeOf(msg_prefix_init), "");
1414 LLVMSetInitializer(msg_prefix, msg_prefix_init);
1415 LLVMSetLinkage(msg_prefix, LLVMPrivateLinkage);
1416 LLVMSetGlobalConstant(msg_prefix, true);
1417
1418 const char *fn_name = get_mangled_name(g, "__zig_fail_unwrap");
1419 LLVMTypeRef fn_type_ref;
1420 if (g->have_err_ret_tracing) {
1421 LLVMTypeRef arg_types[] = {
1422 get_llvm_type(g, get_pointer_to_type(g, get_stack_trace_type(g), false)),
1423 get_llvm_type(g, g->err_tag_type),
1424 };
1425 fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);
1426 } else {
1427 LLVMTypeRef arg_types[] = {
1428 get_llvm_type(g, g->err_tag_type),
1429 };
1430 fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false);
1431 }
1432 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref);
1433 addLLVMFnAttr(fn_val, "noreturn");
1434 addLLVMFnAttr(fn_val, "cold");
1435 LLVMSetLinkage(fn_val, LLVMInternalLinkage);
1436 ZigLLVMFunctionSetCallingConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
1437 add_common_fn_attributes(g, fn_val);
1438 if (!g->omit_frame_pointer) {
1439 ZigLLVMAddFunctionAttr(fn_val, "frame-pointer", "all");
1440 }
1441 // Not setting alignment here. See the comment above about
1442 // "Cannot getTypeInfo() on a type that is unsized!"
1443 // assertion failure on Darwin.
1444
1445 LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry");
1446 LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder);
1447 LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder);
1448 LLVMPositionBuilderAtEnd(g->builder, entry_block);
1449 ZigLLVMClearCurrentDebugLocation(g->builder);
1450
1451 ZigType *usize_ty = g->builtin_types.entry_usize;
1452 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
1453 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false);
1454 ZigType *str_type = get_slice_type(g, u8_ptr_type);
1455
1456 // Allocate a buffer to hold the fully-formatted error message
1457 const size_t err_buf_len = strlen(unwrap_err_msg_text) + g->largest_err_name_len;
1458 LLVMValueRef max_msg_len = LLVMConstInt(usize_ty->llvm_type, err_buf_len, 0);
1459 LLVMValueRef msg_buffer = LLVMBuildArrayAlloca(g->builder, LLVMInt8Type(), max_msg_len, "msg_buffer");
1460
1461 // Allocate a []u8 slice for the message
1462 LLVMValueRef msg_slice = build_alloca(g, str_type, "msg_slice", 0);
1463
1464 LLVMValueRef err_ret_trace_arg;
1465 LLVMValueRef err_val;
1466 if (g->have_err_ret_tracing) {
1467 err_ret_trace_arg = LLVMGetParam(fn_val, 0);
1468 err_val = LLVMGetParam(fn_val, 1);
1469 } else {
1470 err_ret_trace_arg = nullptr;
1471 err_val = LLVMGetParam(fn_val, 0);
1472 }
1473
1474 // Fetch the error name from the global table
1475 LLVMValueRef err_table_indices[] = {
1476 LLVMConstNull(usize_ty->llvm_type),
1477 err_val,
1478 };
1479 LLVMValueRef err_name_val = LLVMBuildInBoundsGEP2(g->builder,
1480 LLVMGlobalGetValueType(g->err_name_table),
1481 g->err_name_table, err_table_indices, 2, "");
1482
1483 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder,
1484 ZigLLVMGetGEPResultElementType(err_name_val), err_name_val, slice_ptr_index, "");
1485 LLVMValueRef err_name_ptr = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_field_ptr),
1486 ptr_field_ptr, 0, false, "");
1487
1488 LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder,
1489 ZigLLVMGetGEPResultElementType(err_name_val), err_name_val, slice_len_index, "");
1490 LLVMValueRef err_name_len = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_field_ptr),
1491 len_field_ptr, 0, false, "");
1492
1493 LLVMValueRef msg_prefix_len = LLVMConstInt(usize_ty->llvm_type, strlen(unwrap_err_msg_text), false);
1494 // Points to the beginning of msg_buffer
1495 LLVMValueRef msg_buffer_ptr_indices[] = {
1496 LLVMConstNull(usize_ty->llvm_type),
1497 };
1498 LLVMValueRef msg_buffer_ptr = LLVMBuildInBoundsGEP2(g->builder, LLVMInt8Type(), msg_buffer,
1499 msg_buffer_ptr_indices, 1, "");
1500 // Points to the beginning of the constant prefix message
1501 LLVMValueRef msg_prefix_ptr_indices[] = {
1502 LLVMConstNull(usize_ty->llvm_type),
1503 };
1504 LLVMValueRef msg_prefix_ptr = LLVMConstInBoundsGEP2(LLVMInt8Type(), msg_prefix, msg_prefix_ptr_indices, 1);
1505
1506 // Build the message using the prefix...
1507 ZigLLVMBuildMemCpy(g->builder, msg_buffer_ptr, 1, msg_prefix_ptr, 1, msg_prefix_len, false);
1508 // ..and append the error name
1509 LLVMValueRef msg_buffer_ptr_after_indices[] = {
1510 msg_prefix_len,
1511 };
1512 LLVMValueRef msg_buffer_ptr_after = LLVMBuildInBoundsGEP2(g->builder, LLVMInt8Type(), msg_buffer, msg_buffer_ptr_after_indices, 1, "");
1513 ZigLLVMBuildMemCpy(g->builder, msg_buffer_ptr_after, 1, err_name_ptr, 1, err_name_len, false);
1514
1515 // Set the slice pointer
1516 LLVMValueRef msg_slice_ptr_field_ptr = LLVMBuildStructGEP2(g->builder,
1517 get_llvm_type(g, str_type), msg_slice, slice_ptr_index, "");
1518 gen_store_untyped(g, msg_buffer_ptr, msg_slice_ptr_field_ptr, 0, false);
1519
1520 // Set the slice length
1521 LLVMValueRef slice_len = LLVMBuildNUWAdd(g->builder, msg_prefix_len, err_name_len, "");
1522 LLVMValueRef msg_slice_len_field_ptr = LLVMBuildStructGEP2(g->builder,
1523 get_llvm_type(g, str_type), msg_slice, slice_len_index, "");
1524 gen_store_untyped(g, slice_len, msg_slice_len_field_ptr, 0, false);
1525
1526 // Call panic()
1527 gen_panic(g, msg_slice, err_ret_trace_arg, false);
1528
1529 LLVMPositionBuilderAtEnd(g->builder, prev_block);
1530 if (!g->strip_debug_symbols) {
1531 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
1532 }
1533
1534 g->safety_crash_err_fn = fn_val;
1535 return fn_val;
1536}
1537
1538static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope, bool *is_llvm_alloca) {
1539 if (!g->have_err_ret_tracing) {
1540 *is_llvm_alloca = false;
1541 return nullptr;
1542 }
1543 if (g->cur_err_ret_trace_val_stack != nullptr) {
1544 *is_llvm_alloca = !fn_is_async(g->cur_fn);
1545 return g->cur_err_ret_trace_val_stack;
1546 }
1547 *is_llvm_alloca = false;
1548 return g->cur_err_ret_trace_val_arg;
1549}
1550
1551static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *scope) {
1552 LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g);
1553 LLVMValueRef call_instruction;
1554 bool is_llvm_alloca = false;
1555 if (g->have_err_ret_tracing) {
1556 LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, scope, &is_llvm_alloca);
1557 if (err_ret_trace_val == nullptr) {
1558 err_ret_trace_val = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type(g)));
1559 }
1560 LLVMValueRef args[] = {
1561 err_ret_trace_val,
1562 err_val,
1563 };
1564 call_instruction = ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(safety_crash_err_fn),
1565 safety_crash_err_fn, args, 2,
1566 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
1567 } else {
1568 LLVMValueRef args[] = {
1569 err_val,
1570 };
1571 call_instruction = ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(safety_crash_err_fn),
1572 safety_crash_err_fn, args, 1,
1573 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
1574 }
1575 if (!is_llvm_alloca) {
1576 LLVMSetTailCall(call_instruction, true);
1577 }
1578 LLVMBuildUnreachable(g->builder);
1579}
1580
1581static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,
1582 LLVMIntPredicate lower_pred, LLVMValueRef lower_value,
1583 LLVMIntPredicate upper_pred, LLVMValueRef upper_value)
1584{
1585 if (!lower_value && !upper_value) {
1586 return;
1587 }
1588 if (upper_value && !lower_value) {
1589 lower_value = upper_value;
1590 lower_pred = upper_pred;
1591 upper_value = nullptr;
1592 }
1593
1594 LLVMBasicBlockRef bounds_check_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "BoundsCheckFail");
1595 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "BoundsCheckOk");
1596 LLVMBasicBlockRef lower_ok_block = upper_value ?
1597 LLVMAppendBasicBlock(g->cur_fn_val, "FirstBoundsCheckOk") : ok_block;
1598
1599 LLVMValueRef lower_ok_val = LLVMBuildICmp(g->builder, lower_pred, target_val, lower_value, "");
1600 LLVMBuildCondBr(g->builder, lower_ok_val, lower_ok_block, bounds_check_fail_block);
1601
1602 LLVMPositionBuilderAtEnd(g->builder, bounds_check_fail_block);
1603 gen_safety_crash(g, PanicMsgIdBoundsCheckFailure);
1604
1605 if (upper_value) {
1606 LLVMPositionBuilderAtEnd(g->builder, lower_ok_block);
1607 LLVMValueRef upper_ok_val = LLVMBuildICmp(g->builder, upper_pred, target_val, upper_value, "");
1608 LLVMBuildCondBr(g->builder, upper_ok_val, ok_block, bounds_check_fail_block);
1609 }
1610
1611 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1612}
1613
1614static void add_sentinel_check(CodeGen *g, LLVMValueRef sentinel_elem_ptr, ZigValue *sentinel) {
1615 LLVMValueRef expected_sentinel = gen_const_val(g, sentinel, "");
1616
1617 LLVMValueRef actual_sentinel = gen_load_untyped(g, LLVMTypeOf(expected_sentinel), sentinel_elem_ptr, 0, false, "");
1618 LLVMValueRef ok_bit;
1619 if (sentinel->type->id == ZigTypeIdFloat) {
1620 ok_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, actual_sentinel, expected_sentinel, "");
1621 } else {
1622 ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, actual_sentinel, expected_sentinel, "");
1623 }
1624
1625 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "SentinelFail");
1626 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "SentinelOk");
1627 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
1628
1629 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1630 gen_safety_crash(g, PanicMsgIdBadSentinel);
1631
1632 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1633}
1634
1635static LLVMValueRef gen_assert_zero(CodeGen *g, LLVMValueRef expr_val, ZigType *int_type) {
1636 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, int_type));
1637 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, zero, "");
1638 if (int_type->id == ZigTypeIdVector) {
1639 ok_bit = ZigLLVMBuildAndReduce(g->builder, ok_bit);
1640 }
1641 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk");
1642 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail");
1643 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
1644
1645 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1646 gen_safety_crash(g, PanicMsgIdCastTruncatedData);
1647
1648 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1649 return nullptr;
1650}
1651
1652static const char *get_compiler_rt_type_abbrev(ZigType *type) {
1653 uint16_t bits;
1654 if (type->id == ZigTypeIdFloat) {
1655 bits = type->data.floating.bit_count;
1656 } else if (type->id == ZigTypeIdInt) {
1657 bits = type->data.integral.bit_count;
1658 } else {
1659 zig_unreachable();
1660 }
1661 switch (bits) {
1662 case 16:
1663 return "h";
1664 case 32:
1665 return "s";
1666 case 64:
1667 return "d";
1668 case 80:
1669 return "x";
1670 case 128:
1671 return "t";
1672 default:
1673 zig_unreachable();
1674 }
1675}
1676
1677static const char *libc_float_prefix(CodeGen *g, ZigType *float_type) {
1678 switch (float_type->data.floating.bit_count) {
1679 case 16:
1680 case 80:
1681 return "__";
1682 case 32:
1683 case 64:
1684 case 128:
1685 return "";
1686 default:
1687 zig_unreachable();
1688 }
1689}
1690
1691static const char *libc_float_suffix(CodeGen *g, ZigType *float_type) {
1692 switch (float_type->size_in_bits) {
1693 case 16: return "h"; // Non-standard
1694 case 32: return "f";
1695 case 64: return "";
1696 case 80: return "x"; // Non-standard
1697 case 128: return "q"; // Non-standard
1698 default: zig_unreachable();
1699 }
1700}
1701
1702static LLVMValueRef gen_soft_float_widen_or_shorten(CodeGen *g, ZigType *actual_type,
1703 ZigType *wanted_type, LLVMValueRef expr_val)
1704{
1705 ZigType *scalar_actual_type = (actual_type->id == ZigTypeIdVector) ?
1706 actual_type->data.vector.elem_type : actual_type;
1707 ZigType *scalar_wanted_type = (wanted_type->id == ZigTypeIdVector) ?
1708 wanted_type->data.vector.elem_type : wanted_type;
1709 uint64_t actual_bits = scalar_actual_type->data.floating.bit_count;
1710 uint64_t wanted_bits = scalar_wanted_type->data.floating.bit_count;
1711
1712 if (actual_bits == wanted_bits)
1713 return expr_val;
1714
1715 LLVMValueRef result;
1716 bool castTruncatedToF16 = false;
1717
1718 char fn_name[64];
1719 if (wanted_bits < actual_bits) {
1720 snprintf(fn_name, sizeof(fn_name), "__trunc%sf%sf2",
1721 get_compiler_rt_type_abbrev(scalar_actual_type),
1722 get_compiler_rt_type_abbrev(scalar_wanted_type));
1723 } else {
1724 snprintf(fn_name, sizeof(fn_name), "__extend%sf%sf2",
1725 get_compiler_rt_type_abbrev(scalar_actual_type),
1726 get_compiler_rt_type_abbrev(scalar_wanted_type));
1727 }
1728
1729 LLVMTypeRef return_type = scalar_wanted_type->llvm_type;
1730 LLVMTypeRef param_type = scalar_actual_type->llvm_type;
1731
1732 if (!target_is_arm(g->zig_target)) {
1733 // Only Arm has a native f16 type, other platforms soft-implement it using u16 instead.
1734 if (scalar_wanted_type == g->builtin_types.entry_f16) {
1735 return_type = g->builtin_types.entry_u16->llvm_type;
1736 castTruncatedToF16 = true;
1737 }
1738 if (scalar_actual_type == g->builtin_types.entry_f16) {
1739 param_type = g->builtin_types.entry_u16->llvm_type;
1740 expr_val = LLVMBuildBitCast(g->builder, expr_val, param_type, "");
1741 }
1742 }
1743
1744 LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, 1, param_type, return_type);
1745 result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, &expr_val, 1, "");
1746
1747 // On non-Arm platforms we need to bitcast __trunc<>fhf2 result back to f16
1748 if (castTruncatedToF16) {
1749 result = LLVMBuildBitCast(g->builder, result, g->builtin_types.entry_f16->llvm_type, "");
1750 }
1751
1752 return result;
1753}
1754
1755static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type,
1756 ZigType *wanted_type, LLVMValueRef expr_val)
1757{
1758 assert(actual_type->id == wanted_type->id);
1759
1760 ZigType *scalar_actual_type = (actual_type->id == ZigTypeIdVector) ?
1761 actual_type->data.vector.elem_type : actual_type;
1762 ZigType *scalar_wanted_type = (wanted_type->id == ZigTypeIdVector) ?
1763 wanted_type->data.vector.elem_type : wanted_type;
1764
1765 uint64_t actual_bits;
1766 uint64_t wanted_bits;
1767 if (scalar_actual_type->id == ZigTypeIdFloat) {
1768
1769 if (((scalar_actual_type == g->builtin_types.entry_f80
1770 || scalar_wanted_type == g->builtin_types.entry_f80)
1771 && !target_has_f80(g->zig_target)) ||
1772 ((scalar_actual_type == g->builtin_types.entry_f16
1773 || scalar_wanted_type == g->builtin_types.entry_f16)
1774 && !target_is_arm(g->zig_target)))
1775 {
1776 return gen_soft_float_widen_or_shorten(g, actual_type, wanted_type, expr_val);
1777 }
1778 actual_bits = scalar_actual_type->data.floating.bit_count;
1779 wanted_bits = scalar_wanted_type->data.floating.bit_count;
1780 } else if (scalar_actual_type->id == ZigTypeIdInt) {
1781 actual_bits = scalar_actual_type->data.integral.bit_count;
1782 wanted_bits = scalar_wanted_type->data.integral.bit_count;
1783 } else {
1784 zig_unreachable();
1785 }
1786
1787 if (expr_val == nullptr) {
1788 if (scalar_actual_type->id == ZigTypeIdInt && actual_bits == 0) {
1789 if (wanted_bits == 0) {
1790 return expr_val;
1791 } else {
1792 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, wanted_type));
1793 return zero;
1794 }
1795 } else {
1796 zig_unreachable();
1797 }
1798 }
1799
1800 if (scalar_actual_type->id == ZigTypeIdInt && want_runtime_safety && (
1801 // negative to unsigned
1802 (!scalar_wanted_type->data.integral.is_signed && scalar_actual_type->data.integral.is_signed) ||
1803 // unsigned would become negative
1804 (scalar_wanted_type->data.integral.is_signed && !scalar_actual_type->data.integral.is_signed && actual_bits == wanted_bits)))
1805 {
1806 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, actual_type));
1807 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntSGE, expr_val, zero, "");
1808
1809 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "SignCastOk");
1810 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "SignCastFail");
1811 if (actual_type->id == ZigTypeIdVector) {
1812 ok_bit = ZigLLVMBuildAndReduce(g->builder, ok_bit);
1813 }
1814 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
1815
1816 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1817 gen_safety_crash(g, scalar_actual_type->data.integral.is_signed ? PanicMsgIdCastNegativeToUnsigned : PanicMsgIdCastTruncatedData);
1818
1819 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1820 }
1821
1822 if (actual_bits == wanted_bits) {
1823 return expr_val;
1824 } else if (actual_bits < wanted_bits) {
1825 if (scalar_actual_type->id == ZigTypeIdFloat) {
1826 return LLVMBuildFPExt(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
1827 } else if (scalar_actual_type->id == ZigTypeIdInt) {
1828 if (scalar_actual_type->data.integral.is_signed) {
1829 return LLVMBuildSExt(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
1830 } else {
1831 return LLVMBuildZExt(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
1832 }
1833 } else {
1834 zig_unreachable();
1835 }
1836 } else if (actual_bits > wanted_bits) {
1837 if (scalar_actual_type->id == ZigTypeIdFloat) {
1838 return LLVMBuildFPTrunc(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
1839 } else if (scalar_actual_type->id == ZigTypeIdInt) {
1840 if (wanted_bits == 0) {
1841 if (!want_runtime_safety)
1842 return nullptr;
1843
1844 return gen_assert_zero(g, expr_val, actual_type);
1845 }
1846 LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
1847 if (!want_runtime_safety) {
1848 return trunc_val;
1849 }
1850 LLVMValueRef orig_val;
1851 if (scalar_wanted_type->data.integral.is_signed) {
1852 orig_val = LLVMBuildSExt(g->builder, trunc_val, get_llvm_type(g, actual_type), "");
1853 } else {
1854 orig_val = LLVMBuildZExt(g->builder, trunc_val, get_llvm_type(g, actual_type), "");
1855 }
1856 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, orig_val, "");
1857 if (actual_type->id == ZigTypeIdVector) {
1858 ok_bit = ZigLLVMBuildAndReduce(g->builder, ok_bit);
1859 }
1860 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk");
1861 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail");
1862 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
1863
1864 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1865 gen_safety_crash(g, PanicMsgIdCastTruncatedData);
1866
1867 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1868 return trunc_val;
1869 } else {
1870 zig_unreachable();
1871 }
1872 } else {
1873 zig_unreachable();
1874 }
1875}
1876
1877typedef LLVMValueRef (*BuildBinOpFunc)(LLVMBuilderRef, LLVMValueRef, LLVMValueRef, const char *);
1878// These are lookup table using the AddSubMul enum as the lookup.
1879// If AddSubMul ever changes, then these tables will be out of
1880// date.
1881static const BuildBinOpFunc float_op[3] = { LLVMBuildFAdd, LLVMBuildFSub, LLVMBuildFMul };
1882static const BuildBinOpFunc wrap_op[3] = { LLVMBuildAdd, LLVMBuildSub, LLVMBuildMul };
1883static const BuildBinOpFunc signed_op[3] = { LLVMBuildNSWAdd, LLVMBuildNSWSub, LLVMBuildNSWMul };
1884static const BuildBinOpFunc unsigned_op[3] = { LLVMBuildNUWAdd, LLVMBuildNUWSub, LLVMBuildNUWMul };
1885
1886static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *operand_type, AddSubMul op,
1887 LLVMValueRef val1, LLVMValueRef val2)
1888{
1889 LLVMValueRef fn_val = get_int_overflow_fn(g, operand_type, op);
1890 LLVMValueRef params[] = {
1891 val1,
1892 val2,
1893 };
1894 LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, "");
1895 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
1896 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
1897 if (operand_type->id == ZigTypeIdVector) {
1898 overflow_bit = ZigLLVMBuildOrReduce(g->builder, overflow_bit);
1899 }
1900
1901 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowFail");
1902 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowOk");
1903 LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block);
1904
1905 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1906 gen_safety_crash(g, PanicMsgIdIntegerOverflow);
1907
1908 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1909 return result;
1910}
1911
1912static LLVMIntPredicate cmp_op_to_int_predicate(IrBinOp cmp_op, bool is_signed) {
1913 switch (cmp_op) {
1914 case IrBinOpCmpEq:
1915 return LLVMIntEQ;
1916 case IrBinOpCmpNotEq:
1917 return LLVMIntNE;
1918 case IrBinOpCmpLessThan:
1919 return is_signed ? LLVMIntSLT : LLVMIntULT;
1920 case IrBinOpCmpGreaterThan:
1921 return is_signed ? LLVMIntSGT : LLVMIntUGT;
1922 case IrBinOpCmpLessOrEq:
1923 return is_signed ? LLVMIntSLE : LLVMIntULE;
1924 case IrBinOpCmpGreaterOrEq:
1925 return is_signed ? LLVMIntSGE : LLVMIntUGE;
1926 default:
1927 zig_unreachable();
1928 }
1929}
1930
1931static LLVMRealPredicate cmp_op_to_real_predicate(IrBinOp cmp_op) {
1932 switch (cmp_op) {
1933 case IrBinOpCmpEq:
1934 return LLVMRealOEQ;
1935 case IrBinOpCmpNotEq:
1936 return LLVMRealUNE;
1937 case IrBinOpCmpLessThan:
1938 return LLVMRealOLT;
1939 case IrBinOpCmpGreaterThan:
1940 return LLVMRealOGT;
1941 case IrBinOpCmpLessOrEq:
1942 return LLVMRealOLE;
1943 case IrBinOpCmpGreaterOrEq:
1944 return LLVMRealOGE;
1945 default:
1946 zig_unreachable();
1947 }
1948}
1949
1950static void gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type,
1951 LLVMValueRef value)
1952{
1953 assert(ptr_type->id == ZigTypeIdPointer);
1954 ZigType *child_type = ptr_type->data.pointer.child_type;
1955
1956 if (!type_has_bits(g, child_type))
1957 return;
1958
1959 if (handle_is_ptr(g, child_type)) {
1960 assert(LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind);
1961 assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind);
1962
1963 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
1964
1965 LLVMValueRef src_ptr = LLVMBuildBitCast(g->builder, value, ptr_u8, "");
1966 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, "");
1967
1968 ZigType *usize = g->builtin_types.entry_usize;
1969 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, get_llvm_type(g, child_type));
1970 uint64_t src_align_bytes = get_abi_alignment(g, child_type);
1971 uint64_t dest_align_bytes = get_ptr_align(g, ptr_type);
1972 assert(size_bytes > 0);
1973 assert(src_align_bytes > 0);
1974 assert(dest_align_bytes > 0);
1975
1976 ZigLLVMBuildMemCpy(g->builder, dest_ptr, dest_align_bytes, src_ptr, src_align_bytes,
1977 LLVMConstInt(usize->llvm_type, size_bytes, false),
1978 ptr_type->data.pointer.is_volatile);
1979 return;
1980 }
1981
1982 assert(ptr_type->data.pointer.vector_index != VECTOR_INDEX_RUNTIME);
1983 if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) {
1984 LLVMValueRef index_val = LLVMConstInt(LLVMInt32Type(),
1985 ptr_type->data.pointer.vector_index, false);
1986 uint32_t vec_len = ptr_type->data.pointer.host_int_bytes;
1987 LLVMTypeRef vec_llvm_ty = LLVMVectorType(get_llvm_type(g, ptr_type->data.pointer.child_type), vec_len);
1988 LLVMValueRef loaded_vector = gen_load_untyped(g, vec_llvm_ty, ptr,
1989 get_ptr_align(g, ptr_type), ptr_type->data.pointer.is_volatile, "");
1990 LLVMValueRef new_vector = LLVMBuildInsertElement(g->builder, loaded_vector, value,
1991 index_val, "");
1992 gen_store(g, new_vector, ptr, ptr_type);
1993 return;
1994 }
1995
1996 uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;
1997 if (host_int_bytes == 0) {
1998 gen_store(g, value, ptr, ptr_type);
1999 return;
2000 }
2001
2002 bool big_endian = g->is_big_endian;
2003
2004 LLVMTypeRef int_ptr_ty = LLVMPointerType(LLVMIntType(host_int_bytes * 8), 0);
2005 LLVMValueRef int_ptr = LLVMBuildBitCast(g->builder, ptr, int_ptr_ty, "");
2006 LLVMValueRef containing_int = gen_load_untyped(g, LLVMIntType(host_int_bytes * 8), int_ptr,
2007 get_ptr_align(g, ptr_type), ptr_type->data.pointer.is_volatile, "");
2008 uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));
2009 assert(host_bit_count == host_int_bytes * 8);
2010 uint32_t size_in_bits = type_size_bits(g, child_type);
2011
2012 uint32_t bit_offset = ptr_type->data.pointer.bit_offset_in_host;
2013 uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - size_in_bits : bit_offset;
2014 LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
2015
2016 // Convert to equally-sized integer type in order to perform the bit
2017 // operations on the value to store
2018 LLVMTypeRef value_bits_type = LLVMIntType(size_in_bits);
2019 LLVMValueRef value_bits = LLVMBuildBitCast(g->builder, value, value_bits_type, "");
2020
2021 LLVMValueRef mask_val = LLVMConstAllOnes(value_bits_type);
2022 mask_val = LLVMConstZExt(mask_val, LLVMTypeOf(containing_int));
2023 mask_val = LLVMConstShl(mask_val, shift_amt_val);
2024 mask_val = LLVMConstNot(mask_val);
2025
2026 LLVMValueRef anded_containing_int = LLVMBuildAnd(g->builder, containing_int, mask_val, "");
2027 LLVMValueRef extended_value = LLVMBuildZExt(g->builder, value_bits, LLVMTypeOf(containing_int), "");
2028 LLVMValueRef shifted_value = LLVMBuildShl(g->builder, extended_value, shift_amt_val, "");
2029 LLVMValueRef ored_value = LLVMBuildOr(g->builder, shifted_value, anded_containing_int, "");
2030
2031 gen_store(g, ored_value, int_ptr, ptr_type);
2032}
2033
2034static void gen_var_debug_decl(CodeGen *g, ZigVar *var) {
2035 if (g->strip_debug_symbols) return;
2036 assert(var->di_loc_var != nullptr);
2037 AstNode *source_node = var->decl_node;
2038 ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc(node_line_onebased(source_node),
2039 node_column_onebased(source_node), get_di_scope(g, var->parent_scope));
2040 ZigLLVMInsertDeclareAtEnd(g->dbuilder, var->value_ref, var->di_loc_var, debug_loc,
2041 LLVMGetInsertBlock(g->builder));
2042}
2043
2044static LLVMValueRef ir_llvm_value(CodeGen *g, Stage1AirInst *instruction) {
2045 Error err;
2046
2047 bool value_has_bits;
2048 if ((err = type_has_bits2(g, instruction->value->type, &value_has_bits)))
2049 codegen_report_errors_and_exit(g);
2050
2051 if (!value_has_bits)
2052 return nullptr;
2053
2054 if (!instruction->llvm_value) {
2055 if (instruction->id == Stage1AirInstIdAwait) {
2056 Stage1AirInstAwait *await = reinterpret_cast<Stage1AirInstAwait*>(instruction);
2057 if (await->result_loc != nullptr) {
2058 return get_handle_value(g, ir_llvm_value(g, await->result_loc),
2059 await->result_loc->value->type->data.pointer.child_type, await->result_loc->value->type);
2060 }
2061 }
2062 if (instruction->spill != nullptr) {
2063 ZigType *ptr_type = instruction->spill->value->type;
2064 ir_assert(ptr_type->id == ZigTypeIdPointer, instruction);
2065 return get_handle_value(g, ir_llvm_value(g, instruction->spill),
2066 ptr_type->data.pointer.child_type, instruction->spill->value->type);
2067 }
2068 ir_assert(instruction->value->special != ConstValSpecialRuntime, instruction);
2069 assert(instruction->value->type);
2070 render_const_val(g, instruction->value, "");
2071 // we might have to do some pointer casting here due to the way union
2072 // values are rendered with a type other than the one we expect
2073 if (handle_is_ptr(g, instruction->value->type)) {
2074 render_const_val_global(g, instruction->value, "");
2075 ZigType *ptr_type = get_pointer_to_type(g, instruction->value->type, true);
2076 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value->llvm_global, get_llvm_type(g, ptr_type), "");
2077 } else {
2078 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value->llvm_value,
2079 get_llvm_type(g, instruction->value->type), "");
2080 }
2081 assert(instruction->llvm_value);
2082 }
2083 return instruction->llvm_value;
2084}
2085
2086void codegen_report_errors_and_exit(CodeGen *g) {
2087 // Clear progress indicator before printing errors
2088 if (g->sub_progress_node != nullptr) {
2089 stage2_progress_end(g->sub_progress_node);
2090 g->sub_progress_node = nullptr;
2091 }
2092 if (g->main_progress_node != nullptr) {
2093 stage2_progress_end(g->main_progress_node);
2094 g->main_progress_node = nullptr;
2095 }
2096
2097 assert(g->errors.length != 0);
2098 for (size_t i = 0; i < g->errors.length; i += 1) {
2099 ErrorMsg *err = g->errors.at(i);
2100 print_err_msg(err, g->err_color);
2101 }
2102 exit(1);
2103}
2104
2105static void report_errors_and_maybe_exit(CodeGen *g) {
2106 if (g->errors.length != 0) {
2107 codegen_report_errors_and_exit(g);
2108 }
2109}
2110
2111ATTRIBUTE_NORETURN
2112static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) {
2113 ErrorMsg *msg = add_node_error(g, source_node,
2114 buf_sprintf("TODO: support C ABI for more targets. https://github.com/ziglang/zig/issues/1481"));
2115 add_error_note(g, msg, source_node,
2116 buf_sprintf("pointers, integers, floats, bools, and enums work on all targets"));
2117 codegen_report_errors_and_exit(g);
2118}
2119
2120static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {
2121 LLVMValueRef result = LLVMBuildAlloca(g->builder, get_llvm_type(g, type_entry), name);
2122 LLVMSetAlignment(result, (alignment == 0) ? get_abi_alignment(g, type_entry) : alignment);
2123 return result;
2124}
2125
2126static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk, size_t src_i) {
2127 // Initialized from the type for some walks, but because of C var args,
2128 // initialized based on callsite instructions for that one.
2129 FnTypeParamInfo *param_info = nullptr;
2130 ZigType *ty;
2131 ZigType *dest_ty = nullptr;
2132 AstNode *source_node = nullptr;
2133 LLVMValueRef val;
2134 LLVMValueRef llvm_fn;
2135 unsigned di_arg_index;
2136 ZigVar *var;
2137 switch (fn_walk->id) {
2138 case FnWalkIdAttrs:
2139 if (src_i >= fn_type->data.fn.fn_type_id.param_count)
2140 return false;
2141 param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];
2142 ty = param_info->type;
2143 source_node = fn_walk->data.attrs.fn->proto_node;
2144 llvm_fn = fn_walk->data.attrs.llvm_fn;
2145 break;
2146 case FnWalkIdCall: {
2147 if (src_i >= fn_walk->data.call.inst->arg_count)
2148 return false;
2149 Stage1AirInst *arg = fn_walk->data.call.inst->args[src_i];
2150 ty = arg->value->type;
2151 source_node = arg->source_node;
2152 val = ir_llvm_value(g, arg);
2153 break;
2154 }
2155 case FnWalkIdTypes:
2156 if (src_i >= fn_type->data.fn.fn_type_id.param_count)
2157 return false;
2158 param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];
2159 ty = param_info->type;
2160 break;
2161 case FnWalkIdVars:
2162 assert(src_i < fn_type->data.fn.fn_type_id.param_count);
2163 param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];
2164 ty = param_info->type;
2165 var = fn_walk->data.vars.var;
2166 source_node = var->decl_node;
2167 llvm_fn = fn_walk->data.vars.llvm_fn;
2168 break;
2169 case FnWalkIdInits:
2170 if (src_i >= fn_type->data.fn.fn_type_id.param_count)
2171 return false;
2172 param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];
2173 ty = param_info->type;
2174 var = fn_walk->data.inits.fn->variable_list.at(src_i);
2175 source_node = fn_walk->data.inits.fn->proto_node;
2176 llvm_fn = fn_walk->data.inits.llvm_fn;
2177 break;
2178 }
2179
2180 if (type_is_c_abi_int_bail(g, ty) || ty->id == ZigTypeIdFloat || ty->id == ZigTypeIdVector ||
2181 ty->id == ZigTypeIdInt // TODO investigate if we need to change this
2182 ) {
2183 switch (fn_walk->id) {
2184 case FnWalkIdAttrs: {
2185 ZigType *ptr_type = get_codegen_ptr_type_bail(g, ty);
2186 if (ptr_type != nullptr) {
2187 if (type_is_nonnull_ptr(g, ty)) {
2188 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
2189 }
2190 if (ptr_type->id == ZigTypeIdPointer && ptr_type->data.pointer.is_const) {
2191 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "readonly");
2192 }
2193 if (param_info->is_noalias) {
2194 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "noalias");
2195 }
2196 }
2197 fn_walk->data.attrs.gen_i += 1;
2198 break;
2199 }
2200 case FnWalkIdCall:
2201 fn_walk->data.call.gen_param_values->append(val);
2202 break;
2203 case FnWalkIdTypes:
2204 fn_walk->data.types.gen_param_types->append(get_llvm_type(g, ty));
2205 fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, ty));
2206 break;
2207 case FnWalkIdVars: {
2208 var->value_ref = build_alloca(g, ty, var->name, var->align_bytes);
2209 di_arg_index = fn_walk->data.vars.gen_i;
2210 fn_walk->data.vars.gen_i += 1;
2211 dest_ty = ty;
2212 goto var_ok;
2213 }
2214 case FnWalkIdInits:
2215 clear_debug_source_node(g);
2216 gen_store_untyped(g, LLVMGetParam(llvm_fn, fn_walk->data.inits.gen_i), var->value_ref, var->align_bytes, false);
2217 if (var->decl_node) {
2218 gen_var_debug_decl(g, var);
2219 }
2220 fn_walk->data.inits.gen_i += 1;
2221 break;
2222 }
2223 return true;
2224 }
2225
2226 {
2227 // Arrays are just pointers
2228 if (ty->id == ZigTypeIdArray) {
2229 assert(handle_is_ptr(g, ty));
2230 switch (fn_walk->id) {
2231 case FnWalkIdAttrs:
2232 // arrays passed to C ABI functions may not be at address 0
2233 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
2234 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
2235 fn_walk->data.attrs.gen_i += 1;
2236 break;
2237 case FnWalkIdCall:
2238 fn_walk->data.call.gen_param_values->append(val);
2239 break;
2240 case FnWalkIdTypes: {
2241 ZigType *gen_type = get_pointer_to_type(g, ty, true);
2242 fn_walk->data.types.gen_param_types->append(get_llvm_type(g, gen_type));
2243 fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, gen_type));
2244 break;
2245 }
2246 case FnWalkIdVars: {
2247 var->value_ref = LLVMGetParam(llvm_fn, fn_walk->data.vars.gen_i);
2248 di_arg_index = fn_walk->data.vars.gen_i;
2249 dest_ty = get_pointer_to_type(g, ty, false);
2250 fn_walk->data.vars.gen_i += 1;
2251 goto var_ok;
2252 }
2253 case FnWalkIdInits:
2254 if (var->decl_node) {
2255 gen_var_debug_decl(g, var);
2256 }
2257 fn_walk->data.inits.gen_i += 1;
2258 break;
2259 }
2260 return true;
2261 }
2262
2263 X64CABIClass abi_class = type_c_abi_x86_64_class(g, ty);
2264 size_t ty_size = type_size(g, ty);
2265 if (abi_class == X64CABIClass_MEMORY || abi_class == X64CABIClass_MEMORY_nobyval) {
2266 assert(handle_is_ptr(g, ty));
2267 switch (fn_walk->id) {
2268 case FnWalkIdAttrs:
2269 if (abi_class != X64CABIClass_MEMORY_nobyval) {
2270 ZigLLVMAddByValAttr(llvm_fn, fn_walk->data.attrs.gen_i, get_llvm_type(g, ty));
2271 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
2272 } else if (g->zig_target->arch == ZigLLVM_aarch64 ||
2273 g->zig_target->arch == ZigLLVM_aarch64_be)
2274 {
2275 // no attrs needed
2276 } else {
2277 if (source_node != nullptr) {
2278 give_up_with_c_abi_error(g, source_node);
2279 }
2280 // otherwise allow codegen code to report a compile error
2281 return false;
2282 }
2283
2284 // Byvalue parameters must not have address 0
2285 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
2286 fn_walk->data.attrs.gen_i += 1;
2287 break;
2288 case FnWalkIdCall:
2289 fn_walk->data.call.gen_param_values->append(val);
2290 break;
2291 case FnWalkIdTypes: {
2292 ZigType *gen_type = get_pointer_to_type(g, ty, true);
2293 fn_walk->data.types.gen_param_types->append(get_llvm_type(g, gen_type));
2294 fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, gen_type));
2295 break;
2296 }
2297 case FnWalkIdVars: {
2298 di_arg_index = fn_walk->data.vars.gen_i;
2299 var->value_ref = LLVMGetParam(llvm_fn, fn_walk->data.vars.gen_i);
2300 dest_ty = get_pointer_to_type(g, ty, false);
2301 fn_walk->data.vars.gen_i += 1;
2302 goto var_ok;
2303 }
2304 case FnWalkIdInits:
2305 if (var->decl_node) {
2306 gen_var_debug_decl(g, var);
2307 }
2308 fn_walk->data.inits.gen_i += 1;
2309 break;
2310 }
2311 return true;
2312 } else if (abi_class == X64CABIClass_INTEGER) {
2313 switch (fn_walk->id) {
2314 case FnWalkIdAttrs:
2315 fn_walk->data.attrs.gen_i += 1;
2316 break;
2317 case FnWalkIdCall: {
2318 LLVMTypeRef int_type_ref = LLVMIntType((unsigned)ty_size * 8);
2319 LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, val, LLVMPointerType(int_type_ref, 0), "");
2320 LLVMValueRef loaded = LLVMBuildLoad2(g->builder, int_type_ref, bitcasted, "");
2321 fn_walk->data.call.gen_param_values->append(loaded);
2322 break;
2323 }
2324 case FnWalkIdTypes: {
2325 ZigType *gen_type = get_int_type(g, false, ty_size * 8);
2326 fn_walk->data.types.gen_param_types->append(get_llvm_type(g, gen_type));
2327 fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, gen_type));
2328 break;
2329 }
2330 case FnWalkIdVars: {
2331 di_arg_index = fn_walk->data.vars.gen_i;
2332 var->value_ref = build_alloca(g, ty, var->name, var->align_bytes);
2333 fn_walk->data.vars.gen_i += 1;
2334 dest_ty = ty;
2335 goto var_ok;
2336 }
2337 case FnWalkIdInits: {
2338 clear_debug_source_node(g);
2339 if (!fn_is_async(fn_walk->data.inits.fn)) {
2340 LLVMValueRef arg = LLVMGetParam(llvm_fn, fn_walk->data.inits.gen_i);
2341 LLVMTypeRef ptr_to_int_type_ref = LLVMPointerType(LLVMIntType((unsigned)ty_size * 8), 0);
2342 LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, var->value_ref, ptr_to_int_type_ref, "");
2343 gen_store_untyped(g, arg, bitcasted, var->align_bytes, false);
2344 }
2345 if (var->decl_node) {
2346 gen_var_debug_decl(g, var);
2347 }
2348 fn_walk->data.inits.gen_i += 1;
2349 break;
2350 }
2351 }
2352 return true;
2353 } else if (abi_class == X64CABIClass_AGG) {
2354 // The SystemV ABI says that we have to setup 1 register per eightbyte.
2355 // So two f32 can be passed in one f64, but 3 f32 have to be passed in 2 FP registers.
2356 // Similarly, two i32 can be passed in one i64, but 3 i32 have to be passed in 2 registers.
2357 // LLVM does not allow us to control registers in this way, nor to request specific
2358 // ABI conventions. So we have to trick it into allocating the right registers, based
2359 // on how clang does it.
2360
2361 // First, we get the LLVM type corresponding to the C abi for the struct, then
2362 // we pass each field as an argument.
2363
2364 // Example:
2365 // extern struct {
2366 // x: f32,
2367 // y: f32,
2368 // z: i32,
2369 // };
2370 // LLVM abi type: { double, i32 }
2371 // const ptr = (*abi_type)*Struct;
2372 // FP Register 1: abi_type[0]
2373 // Register 1: abi_type[1]
2374
2375 // However, if the struct fits in one register, then we'll pass it as such
2376 size_t number_of_regs = (size_t)ceilf((float)ty_size / (float)8);
2377
2378 LLVMTypeRef abi_type = get_llvm_c_abi_type(g, ty);
2379
2380 assert(ty_size <= 16);
2381
2382 switch (fn_walk->id) {
2383 case FnWalkIdAttrs: {
2384 fn_walk->data.attrs.gen_i += number_of_regs;
2385 break;
2386 }
2387 case FnWalkIdCall: {
2388 LLVMValueRef abi_ptr_to_struct = LLVMBuildBitCast(g->builder, val, LLVMPointerType(abi_type, 0), "");
2389 if (number_of_regs == 1) {
2390 LLVMValueRef loaded = LLVMBuildLoad2(g->builder, abi_type, abi_ptr_to_struct, "");
2391 fn_walk->data.call.gen_param_values->append(loaded);
2392 break;
2393 }
2394 for (uint32_t i = 0; i < number_of_regs; i += 1) {
2395 LLVMValueRef adjusted_ptr_to_struct = LLVMBuildStructGEP2(g->builder,
2396 abi_type, abi_ptr_to_struct, i, "");
2397 LLVMTypeRef field_llvm_ty = LLVMStructGetTypeAtIndex(abi_type, i);
2398 LLVMValueRef loaded = LLVMBuildLoad2(g->builder, field_llvm_ty,
2399 adjusted_ptr_to_struct, "");
2400 fn_walk->data.call.gen_param_values->append(loaded);
2401 }
2402 break;
2403 }
2404 case FnWalkIdTypes: {
2405 if (number_of_regs == 1) {
2406 fn_walk->data.types.gen_param_types->append(abi_type);
2407 fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, g->builtin_types.entry_f64));
2408 break;
2409 }
2410 for (uint32_t i = 0; i < number_of_regs; i += 1) {
2411 fn_walk->data.types.gen_param_types->append(LLVMStructGetTypeAtIndex(abi_type, i));
2412 fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, g->builtin_types.entry_f64));
2413 }
2414 break;
2415 }
2416 case FnWalkIdVars: {
2417 var->value_ref = build_alloca(g, ty, var->name, var->align_bytes);
2418 di_arg_index = fn_walk->data.vars.gen_i;
2419 fn_walk->data.vars.gen_i += 1;
2420 dest_ty = ty;
2421 goto var_ok;
2422 }
2423 case FnWalkIdInits: {
2424 // since we're representing the struct differently as an arg, and potentially
2425 // splitting it, we have to do some work to put it back together.
2426 // the one reg case is straightforward, but if we used two registers we have
2427 // to iterate through the struct abi repr fields and load them one by one.
2428 if (number_of_regs == 1) {
2429 LLVMValueRef arg = LLVMGetParam(llvm_fn, fn_walk->data.inits.gen_i);
2430 LLVMTypeRef ptr_to_int_type_ref = LLVMPointerType(abi_type, 0);
2431 LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, var->value_ref, ptr_to_int_type_ref, "");
2432 gen_store_untyped(g, arg, bitcasted, var->align_bytes, false);
2433 } else {
2434 LLVMValueRef abi_ptr_to_struct = LLVMBuildBitCast(g->builder, var->value_ref, LLVMPointerType(abi_type, 0), "");
2435 for (uint32_t i = 0; i < number_of_regs; i += 1) {
2436 LLVMValueRef arg = LLVMGetParam(llvm_fn, fn_walk->data.inits.gen_i + i);
2437 LLVMValueRef zero = LLVMConstInt(LLVMInt32Type(), 0, false);
2438 LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, false);
2439 LLVMValueRef indices[] = { zero, index };
2440 LLVMValueRef adjusted_ptr_to_struct = LLVMBuildInBoundsGEP2(g->builder,
2441 abi_type, abi_ptr_to_struct, indices, 2, "");
2442 LLVMBuildStore(g->builder, arg, adjusted_ptr_to_struct);
2443 }
2444 fn_walk->data.inits.gen_i += 1;
2445 }
2446 if (var->decl_node) {
2447 gen_var_debug_decl(g, var);
2448 }
2449 fn_walk->data.inits.gen_i += 1;
2450 break;
2451 }
2452 }
2453 return true;
2454 }
2455 }
2456 if (source_node != nullptr) {
2457 give_up_with_c_abi_error(g, source_node);
2458 }
2459 // otherwise allow codegen code to report a compile error
2460 return false;
2461
2462var_ok:
2463 if (dest_ty != nullptr && var->decl_node) {
2464 // arg index + 1 because the 0 index is return value
2465 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
2466 var->name, fn_walk->data.vars.import->data.structure.root_struct->di_file,
2467 node_line_onebased(var->decl_node),
2468 get_llvm_di_type(g, dest_ty), !g->strip_debug_symbols, 0, di_arg_index + 1);
2469 }
2470 return true;
2471}
2472
2473void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
2474 CallingConvention cc = fn_type->data.fn.fn_type_id.cc;
2475 if (!calling_convention_allows_zig_types(cc)) {
2476 size_t src_i = 0;
2477 for (;;) {
2478 if (!iter_function_params_c_abi(g, fn_type, fn_walk, src_i))
2479 break;
2480 src_i += 1;
2481 }
2482 return;
2483 }
2484 if (fn_walk->id == FnWalkIdCall) {
2485 Stage1AirInstCall *instruction = fn_walk->data.call.inst;
2486 bool is_var_args = fn_walk->data.call.is_var_args;
2487 for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) {
2488 Stage1AirInst *param_instruction = instruction->args[call_i];
2489 ZigType *param_type = param_instruction->value->type;
2490 if (is_var_args || type_has_bits(g, param_type)) {
2491 LLVMValueRef param_value = ir_llvm_value(g, param_instruction);
2492 assert(param_value);
2493 fn_walk->data.call.gen_param_values->append(param_value);
2494 fn_walk->data.call.gen_param_types->append(param_type);
2495 }
2496 }
2497 return;
2498 }
2499 size_t next_var_i = 0;
2500 for (size_t param_i = 0; param_i < fn_type->data.fn.fn_type_id.param_count; param_i += 1) {
2501 FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i];
2502 size_t gen_index = gen_info->gen_index;
2503
2504 if (gen_index == SIZE_MAX) {
2505 continue;
2506 }
2507
2508 switch (fn_walk->id) {
2509 case FnWalkIdAttrs: {
2510 LLVMValueRef llvm_fn = fn_walk->data.attrs.llvm_fn;
2511 bool is_byval = gen_info->is_byval;
2512 FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[param_i];
2513
2514 ZigType *param_type = gen_info->type;
2515 if (param_info->is_noalias) {
2516 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "noalias");
2517 }
2518 if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {
2519 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly");
2520 }
2521 if (get_codegen_ptr_type_bail(g, param_type) != nullptr) {
2522 addLLVMArgAttrInt(llvm_fn, (unsigned)gen_index, "align", get_ptr_align(g, param_type));
2523 }
2524 if (type_is_nonnull_ptr(g, param_type)) {
2525 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");
2526 }
2527 break;
2528 }
2529 case FnWalkIdInits: {
2530 ZigFn *fn_table_entry = fn_walk->data.inits.fn;
2531 LLVMValueRef llvm_fn = fn_table_entry->llvm_value;
2532 ZigVar *variable = fn_table_entry->variable_list.at(next_var_i);
2533 assert(variable->src_arg_index != SIZE_MAX);
2534 next_var_i += 1;
2535
2536 assert(variable);
2537 assert(variable->value_ref);
2538
2539 if (!handle_is_ptr(g, variable->var_type) && !fn_is_async(fn_walk->data.inits.fn)) {
2540 clear_debug_source_node(g);
2541 ZigType *fn_type = fn_table_entry->type_entry;
2542 unsigned gen_arg_index = fn_type->data.fn.gen_param_info[variable->src_arg_index].gen_index;
2543 gen_store_untyped(g, LLVMGetParam(llvm_fn, gen_arg_index),
2544 variable->value_ref, variable->align_bytes, false);
2545 }
2546
2547 if (variable->decl_node) {
2548 gen_var_debug_decl(g, variable);
2549 }
2550 break;
2551 }
2552 case FnWalkIdCall:
2553 // handled before for loop
2554 zig_unreachable();
2555 case FnWalkIdTypes:
2556 // Not called for non-c-abi
2557 zig_unreachable();
2558 case FnWalkIdVars:
2559 // iter_function_params_c_abi is called directly for this one
2560 zig_unreachable();
2561 }
2562 }
2563}
2564
2565static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
2566 if (g->merge_err_ret_traces_fn_val)
2567 return g->merge_err_ret_traces_fn_val;
2568
2569 assert(g->stack_trace_type != nullptr);
2570
2571 LLVMTypeRef param_types[] = {
2572 get_llvm_type(g, ptr_to_stack_trace_type(g)),
2573 get_llvm_type(g, ptr_to_stack_trace_type(g)),
2574 };
2575 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), param_types, 2, false);
2576
2577 const char *fn_name = get_mangled_name(g, "__zig_merge_error_return_traces");
2578 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref);
2579 LLVMSetLinkage(fn_val, LLVMInternalLinkage);
2580 ZigLLVMFunctionSetCallingConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
2581 add_common_fn_attributes(g, fn_val);
2582 addLLVMArgAttr(fn_val, (unsigned)0, "noalias");
2583 addLLVMArgAttr(fn_val, (unsigned)0, "writeonly");
2584
2585 addLLVMArgAttr(fn_val, (unsigned)1, "noalias");
2586 addLLVMArgAttr(fn_val, (unsigned)1, "readonly");
2587 if (!g->omit_frame_pointer) {
2588 ZigLLVMAddFunctionAttr(fn_val, "frame-pointer", "all");
2589 }
2590
2591 // this is above the ZigLLVMClearCurrentDebugLocation
2592 LLVMValueRef add_error_return_trace_addr_fn_val = get_add_error_return_trace_addr_fn(g);
2593
2594 LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry");
2595 LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder);
2596 LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder);
2597 LLVMPositionBuilderAtEnd(g->builder, entry_block);
2598 ZigLLVMClearCurrentDebugLocation(g->builder);
2599
2600 // if (dest_stack_trace == null or src_stack_trace == null) return;
2601 // var frame_index: usize = undefined;
2602 // var frames_left: usize = undefined;
2603 // if (src_stack_trace.index < src_stack_trace.instruction_addresses.len) {
2604 // frame_index = 0;
2605 // frames_left = src_stack_trace.index;
2606 // if (frames_left == 0) return;
2607 // } else {
2608 // frame_index = (src_stack_trace.index + 1) % src_stack_trace.instruction_addresses.len;
2609 // frames_left = src_stack_trace.instruction_addresses.len;
2610 // }
2611 // while (true) {
2612 // __zig_add_err_ret_trace_addr(dest_stack_trace, src_stack_trace.instruction_addresses[frame_index]);
2613 // frames_left -= 1;
2614 // if (frames_left == 0) return;
2615 // frame_index = (frame_index + 1) % src_stack_trace.instruction_addresses.len;
2616 // }
2617 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(fn_val, "Return");
2618 LLVMBasicBlockRef non_null_block = LLVMAppendBasicBlock(fn_val, "NonNull");
2619
2620 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2621 LLVMValueRef frame_index_ptr = LLVMBuildAlloca(g->builder, usize_type_ref, "frame_index");
2622 LLVMValueRef frames_left_ptr = LLVMBuildAlloca(g->builder, usize_type_ref, "frames_left");
2623
2624 LLVMValueRef dest_stack_trace_ptr = LLVMGetParam(fn_val, 0);
2625 LLVMValueRef src_stack_trace_ptr = LLVMGetParam(fn_val, 1);
2626
2627 LLVMValueRef null_dest_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, dest_stack_trace_ptr,
2628 LLVMConstNull(LLVMTypeOf(dest_stack_trace_ptr)), "");
2629 LLVMValueRef null_src_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, src_stack_trace_ptr,
2630 LLVMConstNull(LLVMTypeOf(src_stack_trace_ptr)), "");
2631 LLVMValueRef null_bit = LLVMBuildOr(g->builder, null_dest_bit, null_src_bit, "");
2632 LLVMBuildCondBr(g->builder, null_bit, return_block, non_null_block);
2633
2634 LLVMPositionBuilderAtEnd(g->builder, non_null_block);
2635 size_t src_index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index;
2636 size_t src_addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index;
2637 LLVMValueRef src_index_field_ptr = LLVMBuildStructGEP2(g->builder,
2638 get_llvm_type(g, g->stack_trace_type), src_stack_trace_ptr,
2639 (unsigned)src_index_field_index, "");
2640 LLVMValueRef src_addresses_field_ptr = LLVMBuildStructGEP2(g->builder,
2641 get_llvm_type(g, g->stack_trace_type), src_stack_trace_ptr,
2642 (unsigned)src_addresses_field_index, "");
2643 ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry;
2644 size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index;
2645 LLVMValueRef src_ptr_field_ptr = LLVMBuildStructGEP2(g->builder,
2646 ZigLLVMGetGEPResultElementType(src_addresses_field_ptr),
2647 src_addresses_field_ptr, (unsigned)ptr_field_index, "");
2648 size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index;
2649 LLVMValueRef src_len_field_ptr = LLVMBuildStructGEP2(g->builder,
2650 ZigLLVMGetGEPResultElementType(src_addresses_field_ptr),
2651 src_addresses_field_ptr, (unsigned)len_field_index, "");
2652 LLVMValueRef src_index_val = LLVMBuildLoad2(g->builder,
2653 ZigLLVMGetGEPResultElementType(src_index_field_ptr), src_index_field_ptr, "");
2654 LLVMValueRef src_ptr_val = LLVMBuildLoad2(g->builder,
2655 ZigLLVMGetGEPResultElementType(src_ptr_field_ptr), src_ptr_field_ptr, "");
2656 LLVMValueRef src_len_val = LLVMBuildLoad2(g->builder,
2657 ZigLLVMGetGEPResultElementType(src_len_field_ptr), src_len_field_ptr, "");
2658 LLVMValueRef no_wrap_bit = LLVMBuildICmp(g->builder, LLVMIntULT, src_index_val, src_len_val, "");
2659 LLVMBasicBlockRef no_wrap_block = LLVMAppendBasicBlock(fn_val, "NoWrap");
2660 LLVMBasicBlockRef yes_wrap_block = LLVMAppendBasicBlock(fn_val, "YesWrap");
2661 LLVMBasicBlockRef loop_block = LLVMAppendBasicBlock(fn_val, "Loop");
2662 LLVMBuildCondBr(g->builder, no_wrap_bit, no_wrap_block, yes_wrap_block);
2663
2664 LLVMPositionBuilderAtEnd(g->builder, no_wrap_block);
2665 LLVMValueRef usize_zero = LLVMConstNull(usize_type_ref);
2666 LLVMBuildStore(g->builder, usize_zero, frame_index_ptr);
2667 LLVMBuildStore(g->builder, src_index_val, frames_left_ptr);
2668 LLVMValueRef frames_left_eq_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, src_index_val, usize_zero, "");
2669 LLVMBuildCondBr(g->builder, frames_left_eq_zero_bit, return_block, loop_block);
2670
2671 LLVMPositionBuilderAtEnd(g->builder, yes_wrap_block);
2672 LLVMValueRef usize_one = LLVMConstInt(usize_type_ref, 1, false);
2673 LLVMValueRef plus_one = LLVMBuildNUWAdd(g->builder, src_index_val, usize_one, "");
2674 LLVMValueRef mod_len = LLVMBuildURem(g->builder, plus_one, src_len_val, "");
2675 LLVMBuildStore(g->builder, mod_len, frame_index_ptr);
2676 LLVMBuildStore(g->builder, src_len_val, frames_left_ptr);
2677 LLVMBuildBr(g->builder, loop_block);
2678
2679 LLVMPositionBuilderAtEnd(g->builder, loop_block);
2680 LLVMValueRef ptr_index = LLVMBuildLoad2(g->builder, usize_type_ref, frame_index_ptr, "");
2681 LLVMValueRef addr_ptr = LLVMBuildInBoundsGEP2(g->builder,
2682 usize_type_ref, src_ptr_val, &ptr_index, 1, "");
2683 LLVMValueRef this_addr_val = LLVMBuildLoad2(g->builder, ZigLLVMGetGEPResultElementType(addr_ptr),
2684 addr_ptr, "");
2685 LLVMValueRef args[] = {dest_stack_trace_ptr, this_addr_val};
2686 ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(add_error_return_trace_addr_fn_val),
2687 add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, "");
2688 LLVMValueRef prev_frames_left = LLVMBuildLoad2(g->builder, usize_type_ref, frames_left_ptr, "");
2689 LLVMValueRef new_frames_left = LLVMBuildNUWSub(g->builder, prev_frames_left, usize_one, "");
2690 LLVMValueRef done_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, new_frames_left, usize_zero, "");
2691 LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(fn_val, "Continue");
2692 LLVMBuildCondBr(g->builder, done_bit, return_block, continue_block);
2693
2694 LLVMPositionBuilderAtEnd(g->builder, return_block);
2695 LLVMBuildRetVoid(g->builder);
2696
2697 LLVMPositionBuilderAtEnd(g->builder, continue_block);
2698 LLVMBuildStore(g->builder, new_frames_left, frames_left_ptr);
2699 LLVMValueRef prev_index = LLVMBuildLoad2(g->builder, usize_type_ref, frame_index_ptr, "");
2700 LLVMValueRef index_plus_one = LLVMBuildNUWAdd(g->builder, prev_index, usize_one, "");
2701 LLVMValueRef index_mod_len = LLVMBuildURem(g->builder, index_plus_one, src_len_val, "");
2702 LLVMBuildStore(g->builder, index_mod_len, frame_index_ptr);
2703 LLVMBuildBr(g->builder, loop_block);
2704
2705 LLVMPositionBuilderAtEnd(g->builder, prev_block);
2706 if (!g->strip_debug_symbols) {
2707 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
2708 }
2709
2710 g->merge_err_ret_traces_fn_val = fn_val;
2711 return fn_val;
2712
2713}
2714static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, Stage1Air *executable,
2715 Stage1AirInstSaveErrRetAddr *save_err_ret_addr_instruction)
2716{
2717 assert(g->have_err_ret_tracing);
2718 if ((target_is_wasm(g->zig_target) && g->zig_target->os != OsEmscripten) || target_is_bpf(g->zig_target)) {
2719 return nullptr;
2720 }
2721
2722 LLVMValueRef return_err_fn = get_return_err_fn(g);
2723 bool is_llvm_alloca;
2724 LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, save_err_ret_addr_instruction->base.scope,
2725 &is_llvm_alloca);
2726 ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(return_err_fn), return_err_fn, &my_err_trace_val, 1,
2727 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
2728
2729 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
2730 if (fn_is_async(g->cur_fn) && codegen_fn_has_err_ret_tracing_arg(g, ret_type)) {
2731 ZigType *frame_type = get_fn_frame_type(g, g->cur_fn);
2732 LLVMValueRef trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, frame_type),
2733 g->cur_frame_ptr, frame_index_trace_arg(g, ret_type), "");
2734 LLVMBuildStore(g->builder, my_err_trace_val, trace_ptr_ptr);
2735 }
2736
2737 return nullptr;
2738}
2739
2740static void gen_assert_resume_id(CodeGen *g, Stage1AirInst *source_instr, ResumeId resume_id, PanicMsgId msg_id,
2741 LLVMBasicBlockRef end_bb)
2742{
2743 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2744
2745 if (ir_want_runtime_safety(g, source_instr)) {
2746 // Write a value to the resume index which indicates the function was resumed while not suspended.
2747 LLVMBuildStore(g->builder, g->cur_bad_not_suspended_index, g->cur_async_resume_index_ptr);
2748 }
2749
2750 LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume");
2751 if (end_bb == nullptr) end_bb = LLVMAppendBasicBlock(g->cur_fn_val, "OkResume");
2752 LLVMValueRef expected_value = LLVMConstSub(LLVMConstAllOnes(usize_type_ref),
2753 LLVMConstInt(usize_type_ref, resume_id, false));
2754 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, LLVMGetParam(g->cur_fn_val, 1), expected_value, "");
2755 LLVMBuildCondBr(g->builder, ok_bit, end_bb, bad_resume_block);
2756
2757 LLVMPositionBuilderAtEnd(g->builder, bad_resume_block);
2758 gen_assertion(g, msg_id, source_instr);
2759
2760 LLVMPositionBuilderAtEnd(g->builder, end_bb);
2761}
2762
2763static LLVMValueRef gen_resume(CodeGen *g, LLVMTypeRef fn_llvm_ty, LLVMValueRef fn_val,
2764 LLVMValueRef target_frame_ptr, ResumeId resume_id)
2765{
2766 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2767 if (fn_val == nullptr) {
2768 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP2(g->builder, g->any_frame_header_llvm_ty,
2769 target_frame_ptr, frame_fn_ptr_index, "");
2770 fn_val = LLVMBuildLoad2(g->builder, ZigLLVMGetGEPResultElementType(fn_ptr_ptr),
2771 fn_ptr_ptr, "");
2772 }
2773 LLVMValueRef arg_val = LLVMConstSub(LLVMConstAllOnes(usize_type_ref),
2774 LLVMConstInt(usize_type_ref, resume_id, false));
2775 LLVMValueRef args[] = {target_frame_ptr, arg_val};
2776 return ZigLLVMBuildCall(g->builder, fn_llvm_ty, fn_val, args, 2, ZigLLVM_Fast,
2777 ZigLLVM_CallAttrAuto, "");
2778}
2779
2780static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {
2781 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2782 LLVMBasicBlockRef resume_bb = LLVMAppendBasicBlock(g->cur_fn_val, name_hint);
2783 size_t new_block_index = g->cur_resume_block_count;
2784 g->cur_resume_block_count += 1;
2785 LLVMValueRef new_block_index_val = LLVMConstInt(usize_type_ref, new_block_index, false);
2786 LLVMAddCase(g->cur_async_switch_instr, new_block_index_val, resume_bb);
2787 LLVMBuildStore(g->builder, new_block_index_val, g->cur_async_resume_index_ptr);
2788 return resume_bb;
2789}
2790
2791// Be careful setting tail call. According to LLVM lang ref,
2792// tail and musttail imply that the callee does not access allocas from the caller.
2793// This works for async functions since the locals are spilled.
2794// http://llvm.org/docs/LangRef.html#id320
2795static void set_tail_call_if_appropriate(CodeGen *g, LLVMValueRef call_inst) {
2796 LLVMSetTailCall(call_inst, true);
2797}
2798
2799static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMValueRef ptr,
2800 LLVMValueRef val, LLVMAtomicOrdering order)
2801{
2802 if (g->is_single_threaded) {
2803 LLVMValueRef loaded = LLVMBuildLoad2(g->builder, LLVMTypeOf(val), ptr, "");
2804 LLVMValueRef modified;
2805 switch (op) {
2806 case LLVMAtomicRMWBinOpXchg:
2807 modified = val;
2808 break;
2809 case LLVMAtomicRMWBinOpXor:
2810 modified = LLVMBuildXor(g->builder, loaded, val, "");
2811 break;
2812 default:
2813 zig_unreachable();
2814 }
2815 LLVMBuildStore(g->builder, modified, ptr);
2816 return loaded;
2817 } else {
2818 return LLVMBuildAtomicRMW(g->builder, op, ptr, val, order, false);
2819 }
2820}
2821
2822static void gen_async_return(CodeGen *g, Stage1AirInstReturn *instruction) {
2823 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2824
2825 ZigType *operand_type = (instruction->operand != nullptr) ? instruction->operand->value->type : nullptr;
2826 bool operand_has_bits = (operand_type != nullptr) && type_has_bits(g, operand_type);
2827 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
2828 bool ret_type_has_bits = type_has_bits(g, ret_type);
2829
2830 if (operand_has_bits && instruction->operand != nullptr) {
2831 bool need_store = instruction->operand->value->special != ConstValSpecialRuntime || !handle_is_ptr(g, ret_type);
2832 if (need_store) {
2833 // It didn't get written to the result ptr. We do that now.
2834 ZigType *ret_ptr_type = get_pointer_to_type(g, ret_type, true);
2835 gen_assign_raw(g, g->cur_ret_ptr, ret_ptr_type, ir_llvm_value(g, instruction->operand));
2836 }
2837 }
2838
2839 // Whether we tail resume the awaiter, or do an early return, we are done and will not be resumed.
2840 if (ir_want_runtime_safety(g, &instruction->base)) {
2841 LLVMValueRef new_resume_index = LLVMConstAllOnes(usize_type_ref);
2842 LLVMBuildStore(g->builder, new_resume_index, g->cur_async_resume_index_ptr);
2843 }
2844
2845 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
2846 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);
2847
2848 LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXor, g->cur_async_awaiter_ptr,
2849 all_ones, LLVMAtomicOrderingAcquire);
2850
2851 LLVMBasicBlockRef bad_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadReturn");
2852 LLVMBasicBlockRef early_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "EarlyReturn");
2853 LLVMBasicBlockRef resume_them_block = LLVMAppendBasicBlock(g->cur_fn_val, "ResumeThem");
2854
2855 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, prev_val, resume_them_block, 2);
2856
2857 LLVMAddCase(switch_instr, zero, early_return_block);
2858 LLVMAddCase(switch_instr, all_ones, bad_return_block);
2859
2860 // Something has gone horribly wrong, and this is an invalid second return.
2861 LLVMPositionBuilderAtEnd(g->builder, bad_return_block);
2862 gen_assertion(g, PanicMsgIdBadReturn, &instruction->base);
2863
2864 // There is no awaiter yet, but we're completely done.
2865 LLVMPositionBuilderAtEnd(g->builder, early_return_block);
2866 LLVMBuildRetVoid(g->builder);
2867
2868 // We need to resume the caller by tail calling them,
2869 // but first write through the result pointer and possibly
2870 // error return trace pointer.
2871 LLVMPositionBuilderAtEnd(g->builder, resume_them_block);
2872
2873 if (ret_type_has_bits) {
2874 // If the awaiter result pointer is non-null, we need to copy the result to there.
2875 LLVMBasicBlockRef copy_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResult");
2876 LLVMBasicBlockRef copy_end_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResultEnd");
2877 LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP2(g->builder,
2878 get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)),
2879 g->cur_frame_ptr, frame_ret_start + 1, "");
2880 LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad2(g->builder,
2881 ZigLLVMGetGEPResultElementType(awaiter_ret_ptr_ptr), awaiter_ret_ptr_ptr, "");
2882 LLVMValueRef zero_ptr = LLVMConstNull(LLVMTypeOf(awaiter_ret_ptr));
2883 LLVMValueRef need_copy_bit = LLVMBuildICmp(g->builder, LLVMIntNE, awaiter_ret_ptr, zero_ptr, "");
2884 LLVMBuildCondBr(g->builder, need_copy_bit, copy_block, copy_end_block);
2885
2886 LLVMPositionBuilderAtEnd(g->builder, copy_block);
2887 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
2888 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, awaiter_ret_ptr, ptr_u8, "");
2889 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, g->cur_ret_ptr, ptr_u8, "");
2890 bool is_volatile = false;
2891 uint32_t abi_align = get_abi_alignment(g, ret_type);
2892 LLVMValueRef byte_count_val = LLVMConstInt(usize_type_ref, type_size(g, ret_type), false);
2893 ZigLLVMBuildMemCpy(g->builder,
2894 dest_ptr_casted, abi_align,
2895 src_ptr_casted, abi_align, byte_count_val, is_volatile);
2896 LLVMBuildBr(g->builder, copy_end_block);
2897
2898 LLVMPositionBuilderAtEnd(g->builder, copy_end_block);
2899 if (codegen_fn_has_err_ret_tracing_arg(g, ret_type)) {
2900 LLVMValueRef awaiter_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder,
2901 get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)),
2902 g->cur_frame_ptr, frame_index_trace_arg(g, ret_type) + 1, "");
2903 LLVMValueRef dest_trace_ptr = LLVMBuildLoad2(g->builder,
2904 ZigLLVMGetGEPResultElementType(awaiter_trace_ptr_ptr),
2905 awaiter_trace_ptr_ptr, "");
2906 bool is_llvm_alloca;
2907 LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca);
2908 LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val };
2909 ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(get_merge_err_ret_traces_fn_val(g)),
2910 get_merge_err_ret_traces_fn_val(g), args, 2,
2911 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
2912 }
2913 }
2914
2915 // Resume the caller by tail calling them.
2916 ZigType *any_frame_type = get_any_frame_type(g, ret_type);
2917 LLVMValueRef their_frame_ptr = LLVMBuildIntToPtr(g->builder, prev_val,
2918 get_llvm_type(g, any_frame_type), "");
2919 LLVMValueRef call_inst = gen_resume(g, g->anyframe_fn_type, nullptr, their_frame_ptr, ResumeIdReturn);
2920 set_tail_call_if_appropriate(g, call_inst);
2921 LLVMBuildRetVoid(g->builder);
2922}
2923
2924static LLVMValueRef gen_convert_to_c_abi(CodeGen *g, LLVMValueRef location, LLVMValueRef value) {
2925 ZigType *return_type = g->cur_fn->type_entry->data.fn.gen_return_type;
2926 size_t size = type_size(g, return_type);
2927 LLVMTypeRef abi_return_type = get_llvm_c_abi_type(g, return_type);
2928 LLVMTypeRef abi_return_type_pointer = LLVMPointerType(abi_return_type, 0);
2929
2930 if (size < 8) {
2931 LLVMValueRef bitcast = LLVMBuildBitCast(g->builder, value, abi_return_type_pointer, "");
2932 return LLVMBuildLoad2(g->builder, abi_return_type, bitcast, "");
2933 } else {
2934 LLVMTypeRef i8ptr = LLVMPointerType(LLVMInt8Type(), 0);
2935 LLVMValueRef bc_location = LLVMBuildBitCast(g->builder, location, i8ptr, "");
2936 LLVMValueRef bc_value = LLVMBuildBitCast(g->builder, value, i8ptr, "");
2937
2938 LLVMValueRef len = LLVMConstInt(LLVMInt64Type(), size, false);
2939 ZigLLVMBuildMemCpy(g->builder, bc_location, 8, bc_value, return_type->abi_align, len, false);
2940 return LLVMBuildLoad2(g->builder, abi_return_type, location, "");
2941 }
2942}
2943
2944static LLVMValueRef ir_render_return(CodeGen *g, Stage1Air *executable, Stage1AirInstReturn *instruction) {
2945 if (fn_is_async(g->cur_fn)) {
2946 gen_async_return(g, instruction);
2947 return nullptr;
2948 }
2949
2950 FnTypeId *fn_type_id = &g->cur_fn->type_entry->data.fn.fn_type_id;
2951
2952 if (want_first_arg_sret(g, fn_type_id)) {
2953 if (instruction->operand == nullptr) {
2954 LLVMBuildRetVoid(g->builder);
2955 return nullptr;
2956 }
2957 assert(g->cur_ret_ptr);
2958 ir_assert(instruction->operand->value->special != ConstValSpecialRuntime, &instruction->base);
2959 LLVMValueRef value = ir_llvm_value(g, instruction->operand);
2960 ZigType *return_type = instruction->operand->value->type;
2961 gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
2962 LLVMBuildRetVoid(g->builder);
2963 } else if (fn_returns_c_abi_small_struct(fn_type_id)) {
2964 LLVMValueRef location = g->cur_fn->abi_return_value;
2965 if (instruction->operand == nullptr) {
2966 LLVMValueRef converted = gen_convert_to_c_abi(g, location, g->cur_ret_ptr);
2967 LLVMBuildRet(g->builder, converted);
2968 } else {
2969 LLVMValueRef value = ir_llvm_value(g, instruction->operand);
2970 LLVMValueRef converted = gen_convert_to_c_abi(g, location, value);
2971 LLVMBuildRet(g->builder, converted);
2972 }
2973 } else if (g->cur_fn->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync &&
2974 handle_is_ptr(g, g->cur_fn->type_entry->data.fn.fn_type_id.return_type))
2975 {
2976 LLVMTypeRef ret_llvm_ty = get_llvm_type(g, g->cur_fn->type_entry->data.fn.fn_type_id.return_type);
2977 if (instruction->operand == nullptr) {
2978 LLVMValueRef by_val_value = gen_load_untyped(g, ret_llvm_ty, g->cur_ret_ptr, 0, false, "");
2979 LLVMBuildRet(g->builder, by_val_value);
2980 } else {
2981 LLVMValueRef value = ir_llvm_value(g, instruction->operand);
2982 LLVMValueRef by_val_value = gen_load_untyped(g, ret_llvm_ty, value, 0, false, "");
2983 LLVMBuildRet(g->builder, by_val_value);
2984 }
2985 } else if (instruction->operand == nullptr) {
2986 if (g->cur_ret_ptr == nullptr) {
2987 LLVMBuildRetVoid(g->builder);
2988 } else {
2989 LLVMTypeRef ret_llvm_ty = get_llvm_type(g, g->cur_fn->type_entry->data.fn.fn_type_id.return_type);
2990 LLVMValueRef by_val_value = gen_load_untyped(g, ret_llvm_ty, g->cur_ret_ptr, 0, false, "");
2991 LLVMBuildRet(g->builder, by_val_value);
2992 }
2993 } else {
2994 LLVMValueRef value = ir_llvm_value(g, instruction->operand);
2995 LLVMBuildRet(g->builder, value);
2996 }
2997 return nullptr;
2998}
2999
3000static LLVMValueRef gen_overflow_shl_op(CodeGen *g, ZigType *operand_type,
3001 LLVMValueRef val1, LLVMValueRef val2)
3002{
3003 // for unsigned left shifting, we do the lossy shift, then logically shift
3004 // right the same number of bits
3005 // if the values don't match, we have an overflow
3006 // for signed left shifting we do the same except arithmetic shift right
3007 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ?
3008 operand_type->data.vector.elem_type : operand_type;
3009
3010 assert(scalar_type->id == ZigTypeIdInt);
3011
3012 LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, "");
3013 LLVMValueRef orig_val;
3014 if (scalar_type->data.integral.is_signed) {
3015 orig_val = LLVMBuildAShr(g->builder, result, val2, "");
3016 } else {
3017 orig_val = LLVMBuildLShr(g->builder, result, val2, "");
3018 }
3019 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, orig_val, "");
3020
3021 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowOk");
3022 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowFail");
3023 if (operand_type->id == ZigTypeIdVector) {
3024 ok_bit = ZigLLVMBuildAndReduce(g->builder, ok_bit);
3025 }
3026 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
3027
3028 LLVMPositionBuilderAtEnd(g->builder, fail_block);
3029 gen_safety_crash(g, PanicMsgIdShlOverflowedBits);
3030
3031 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3032 return result;
3033}
3034
3035static LLVMValueRef gen_overflow_shr_op(CodeGen *g, ZigType *operand_type,
3036 LLVMValueRef val1, LLVMValueRef val2)
3037{
3038 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ?
3039 operand_type->data.vector.elem_type : operand_type;
3040
3041 assert(scalar_type->id == ZigTypeIdInt);
3042
3043 LLVMValueRef result;
3044 if (scalar_type->data.integral.is_signed) {
3045 result = LLVMBuildAShr(g->builder, val1, val2, "");
3046 } else {
3047 result = LLVMBuildLShr(g->builder, val1, val2, "");
3048 }
3049 LLVMValueRef orig_val = LLVMBuildShl(g->builder, result, val2, "");
3050 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, orig_val, "");
3051
3052 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowOk");
3053 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowFail");
3054 if (operand_type->id == ZigTypeIdVector) {
3055 ok_bit = ZigLLVMBuildAndReduce(g->builder, ok_bit);
3056 }
3057 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
3058
3059 LLVMPositionBuilderAtEnd(g->builder, fail_block);
3060 gen_safety_crash(g, PanicMsgIdShrOverflowedBits);
3061
3062 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3063 return result;
3064}
3065
3066static LLVMValueRef get_soft_float_fn(CodeGen *g, const char *name, int param_count, LLVMTypeRef param_type, LLVMTypeRef return_type) {
3067 LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, name);
3068 if (existing_llvm_fn != nullptr) return existing_llvm_fn;
3069 LLVMValueRef existing_llvm_alias = LLVMGetNamedGlobalAlias(g->module, name, strlen(name));
3070 if (existing_llvm_alias != nullptr) return LLVMAliasGetAliasee(existing_llvm_alias);
3071
3072 LLVMTypeRef param_types[3] = { param_type, param_type, param_type };
3073 LLVMTypeRef fn_type = LLVMFunctionType(return_type, param_types, param_count, false);
3074 return LLVMAddFunction(g->module, name, fn_type);
3075}
3076
3077static LLVMValueRef gen_soft_float_un_op(CodeGen *g, LLVMValueRef op, ZigType *operand_type, BuiltinFnId op_id) {
3078 uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0;
3079 ZigType *scalar_type = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.elem_type : operand_type;
3080
3081 char fn_name[64];
3082 snprintf(fn_name, sizeof(fn_name), "%s%s%s", libc_float_prefix(g, scalar_type),
3083 float_un_op_to_name(op_id), libc_float_suffix(g, scalar_type));
3084 LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, 1, scalar_type->llvm_type, scalar_type->llvm_type);
3085
3086 if (vector_len == 0) {
3087 return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, &op, 1, "");
3088 } else {
3089 LLVMValueRef result = LLVMGetUndef(operand_type->llvm_type);
3090 LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type;
3091 for (uint32_t i = 0; i < vector_len; i++) {
3092 LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false);
3093 LLVMValueRef param = LLVMBuildExtractElement(g->builder, op, index_value, "");
3094 LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, &param, 1, "");
3095 result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, "");
3096 }
3097 return result;
3098 }
3099}
3100
3101static LLVMValueRef gen_float_un_op(CodeGen *g, LLVMValueRef operand, ZigType *operand_type, BuiltinFnId op) {
3102 assert(operand_type->id == ZigTypeIdFloat || operand_type->id == ZigTypeIdVector);
3103 ZigType *elem_type = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.elem_type : operand_type;
3104 if ((elem_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) ||
3105 (elem_type == g->builtin_types.entry_f128 && !target_long_double_is_f128(g->zig_target)) ||
3106 (elem_type == g->builtin_types.entry_f16 && !target_is_arm(g->zig_target)) ||
3107 op == BuiltinFnIdTan)
3108 {
3109 return gen_soft_float_un_op(g, operand, operand_type, op);
3110 }
3111 LLVMValueRef float_op_fn = get_float_fn(g, operand_type, ZigLLVMFnIdFloatOp, op);
3112 return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(float_op_fn), float_op_fn, &operand, 1, "");
3113}
3114
3115enum DivKind {
3116 DivKindFloat,
3117 DivKindTrunc,
3118 DivKindFloor,
3119 DivKindExact,
3120};
3121
3122static LLVMValueRef bigint_to_llvm_const(LLVMTypeRef type_ref, BigInt *bigint) {
3123 if (bigint->digit_count == 0) {
3124 return LLVMConstNull(type_ref);
3125 }
3126
3127 if (LLVMGetTypeKind(type_ref) == LLVMVectorTypeKind) {
3128 const unsigned vector_len = LLVMGetVectorSize(type_ref);
3129 LLVMTypeRef elem_type = LLVMGetElementType(type_ref);
3130
3131 LLVMValueRef *values = heap::c_allocator.allocate_nonzero<LLVMValueRef>(vector_len);
3132 // Create a vector with all the elements having the same value
3133 for (unsigned i = 0; i < vector_len; i++) {
3134 values[i] = bigint_to_llvm_const(elem_type, bigint);
3135 }
3136 LLVMValueRef result = LLVMConstVector(values, vector_len);
3137 heap::c_allocator.deallocate(values, vector_len);
3138 return result;
3139 }
3140
3141 LLVMValueRef unsigned_val;
3142 if (bigint->digit_count == 1) {
3143 unsigned_val = LLVMConstInt(type_ref, bigint_ptr(bigint)[0], false);
3144 } else {
3145 unsigned_val = LLVMConstIntOfArbitraryPrecision(type_ref, bigint->digit_count, bigint_ptr(bigint));
3146 }
3147 if (bigint->is_negative) {
3148 return LLVMConstNeg(unsigned_val);
3149 } else {
3150 return unsigned_val;
3151 }
3152}
3153
3154static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast_math,
3155 LLVMValueRef val1, LLVMValueRef val2, ZigType *operand_type, DivKind div_kind)
3156{
3157 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ?
3158 operand_type->data.vector.elem_type : operand_type;
3159
3160 ZigLLVMSetFastMath(g->builder, want_fast_math);
3161
3162 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, operand_type));
3163 if (want_runtime_safety && (want_fast_math || scalar_type->id != ZigTypeIdFloat)) {
3164 // Safety check: divisor != 0
3165 LLVMValueRef is_zero_bit;
3166 if (scalar_type->id == ZigTypeIdInt) {
3167 is_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, zero, "");
3168 } else if (scalar_type->id == ZigTypeIdFloat) {
3169 is_zero_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, val2, zero, "");
3170 } else {
3171 zig_unreachable();
3172 }
3173
3174 if (operand_type->id == ZigTypeIdVector) {
3175 is_zero_bit = ZigLLVMBuildOrReduce(g->builder, is_zero_bit);
3176 }
3177
3178 LLVMBasicBlockRef div_zero_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroFail");
3179 LLVMBasicBlockRef div_zero_ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroOk");
3180 LLVMBuildCondBr(g->builder, is_zero_bit, div_zero_fail_block, div_zero_ok_block);
3181
3182 LLVMPositionBuilderAtEnd(g->builder, div_zero_fail_block);
3183 gen_safety_crash(g, PanicMsgIdDivisionByZero);
3184
3185 LLVMPositionBuilderAtEnd(g->builder, div_zero_ok_block);
3186
3187 // Safety check: check for overflow (dividend = minInt and divisor = -1)
3188 if (scalar_type->id == ZigTypeIdInt && scalar_type->data.integral.is_signed) {
3189 LLVMValueRef neg_1_value = LLVMConstAllOnes(get_llvm_type(g, operand_type));
3190 BigInt int_min_bi = {0};
3191 eval_min_max_value_int(g, scalar_type, &int_min_bi, false);
3192 LLVMValueRef int_min_value = bigint_to_llvm_const(get_llvm_type(g, operand_type), &int_min_bi);
3193
3194 LLVMBasicBlockRef overflow_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowFail");
3195 LLVMBasicBlockRef overflow_ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowOk");
3196 LLVMValueRef num_is_int_min = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, int_min_value, "");
3197 LLVMValueRef den_is_neg_1 = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, neg_1_value, "");
3198 LLVMValueRef overflow_fail_bit = LLVMBuildAnd(g->builder, num_is_int_min, den_is_neg_1, "");
3199 if (operand_type->id == ZigTypeIdVector) {
3200 overflow_fail_bit = ZigLLVMBuildOrReduce(g->builder, overflow_fail_bit);
3201 }
3202 LLVMBuildCondBr(g->builder, overflow_fail_bit, overflow_fail_block, overflow_ok_block);
3203
3204 LLVMPositionBuilderAtEnd(g->builder, overflow_fail_block);
3205 gen_safety_crash(g, PanicMsgIdIntegerOverflow);
3206
3207 LLVMPositionBuilderAtEnd(g->builder, overflow_ok_block);
3208 }
3209 }
3210
3211 if (scalar_type->id == ZigTypeIdFloat) {
3212 LLVMValueRef result = LLVMBuildFDiv(g->builder, val1, val2, "");
3213 switch (div_kind) {
3214 case DivKindFloat:
3215 return result;
3216 case DivKindExact:
3217 if (want_runtime_safety) {
3218 // Safety check: a / b == floor(a / b)
3219 LLVMValueRef floored = gen_float_un_op(g, result, operand_type, BuiltinFnIdFloor);
3220
3221 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactOk");
3222 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactFail");
3223 LLVMValueRef ok_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, floored, result, "");
3224 if (operand_type->id == ZigTypeIdVector) {
3225 ok_bit = ZigLLVMBuildAndReduce(g->builder, ok_bit);
3226 }
3227 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
3228
3229 LLVMPositionBuilderAtEnd(g->builder, fail_block);
3230 gen_safety_crash(g, PanicMsgIdExactDivisionRemainder);
3231
3232 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3233 }
3234 return result;
3235 case DivKindTrunc:
3236 return gen_float_un_op(g, result, operand_type, BuiltinFnIdTrunc);
3237 case DivKindFloor:
3238 return gen_float_un_op(g, result, operand_type, BuiltinFnIdFloor);
3239 }
3240 zig_unreachable();
3241 }
3242
3243 assert(scalar_type->id == ZigTypeIdInt);
3244
3245 switch (div_kind) {
3246 case DivKindFloat:
3247 zig_unreachable();
3248 case DivKindTrunc:
3249 if (scalar_type->data.integral.is_signed) {
3250 return LLVMBuildSDiv(g->builder, val1, val2, "");
3251 } else {
3252 return LLVMBuildUDiv(g->builder, val1, val2, "");
3253 }
3254 case DivKindExact:
3255 if (want_runtime_safety) {
3256 // Safety check: a % b == 0
3257 LLVMValueRef remainder_val;
3258 if (scalar_type->data.integral.is_signed) {
3259 remainder_val = LLVMBuildSRem(g->builder, val1, val2, "");
3260 } else {
3261 remainder_val = LLVMBuildURem(g->builder, val1, val2, "");
3262 }
3263
3264 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactOk");
3265 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactFail");
3266 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, "");
3267 if (operand_type->id == ZigTypeIdVector) {
3268 ok_bit = ZigLLVMBuildAndReduce(g->builder, ok_bit);
3269 }
3270 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
3271
3272 LLVMPositionBuilderAtEnd(g->builder, fail_block);
3273 gen_safety_crash(g, PanicMsgIdExactDivisionRemainder);
3274
3275 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3276 }
3277 if (scalar_type->data.integral.is_signed) {
3278 return LLVMBuildExactSDiv(g->builder, val1, val2, "");
3279 } else {
3280 return LLVMBuildExactUDiv(g->builder, val1, val2, "");
3281 }
3282 case DivKindFloor:
3283 {
3284 if (!scalar_type->data.integral.is_signed) {
3285 return LLVMBuildUDiv(g->builder, val1, val2, "");
3286 }
3287 // const d = @divTrunc(a, b);
3288 // const r = @rem(a, b);
3289 // return if (r == 0) d else d - ((a < 0) ^ (b < 0));
3290
3291 LLVMValueRef div_trunc = LLVMBuildSDiv(g->builder, val1, val2, "");
3292 LLVMValueRef rem = LLVMBuildSRem(g->builder, val1, val2, "");
3293 LLVMValueRef rem_eq_0 = LLVMBuildICmp(g->builder, LLVMIntEQ, rem, zero, "");
3294 LLVMValueRef a_lt_0 = LLVMBuildICmp(g->builder, LLVMIntSLT, val1, zero, "");
3295 LLVMValueRef b_lt_0 = LLVMBuildICmp(g->builder, LLVMIntSLT, val2, zero, "");
3296 LLVMValueRef a_b_xor = LLVMBuildXor(g->builder, a_lt_0, b_lt_0, "");
3297 LLVMValueRef a_b_xor_ext = LLVMBuildZExt(g->builder, a_b_xor, LLVMTypeOf(div_trunc), "");
3298 LLVMValueRef d_sub_xor = LLVMBuildSub(g->builder, div_trunc, a_b_xor_ext, "");
3299 return LLVMBuildSelect(g->builder, rem_eq_0, div_trunc, d_sub_xor, "");
3300 }
3301 }
3302 zig_unreachable();
3303}
3304
3305enum RemKind {
3306 RemKindRem,
3307 RemKindMod,
3308};
3309
3310static LLVMValueRef gen_rem(CodeGen *g, bool want_runtime_safety, bool want_fast_math,
3311 LLVMValueRef val1, LLVMValueRef val2, ZigType *operand_type, RemKind rem_kind)
3312{
3313 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ?
3314 operand_type->data.vector.elem_type : operand_type;
3315
3316 ZigLLVMSetFastMath(g->builder, want_fast_math);
3317
3318 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, operand_type));
3319 if (want_runtime_safety) {
3320 // Safety check: divisor != 0
3321 LLVMValueRef is_zero_bit;
3322 if (scalar_type->id == ZigTypeIdInt) {
3323 LLVMIntPredicate pred = scalar_type->data.integral.is_signed ? LLVMIntSLE : LLVMIntEQ;
3324 is_zero_bit = LLVMBuildICmp(g->builder, pred, val2, zero, "");
3325 } else if (scalar_type->id == ZigTypeIdFloat) {
3326 is_zero_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, val2, zero, "");
3327 } else {
3328 zig_unreachable();
3329 }
3330
3331 if (operand_type->id == ZigTypeIdVector) {
3332 is_zero_bit = ZigLLVMBuildOrReduce(g->builder, is_zero_bit);
3333 }
3334
3335 LLVMBasicBlockRef rem_zero_ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "RemZeroOk");
3336 LLVMBasicBlockRef rem_zero_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "RemZeroFail");
3337 LLVMBuildCondBr(g->builder, is_zero_bit, rem_zero_fail_block, rem_zero_ok_block);
3338
3339 LLVMPositionBuilderAtEnd(g->builder, rem_zero_fail_block);
3340 gen_safety_crash(g, PanicMsgIdRemainderDivisionByZero);
3341
3342 LLVMPositionBuilderAtEnd(g->builder, rem_zero_ok_block);
3343 }
3344
3345 if (scalar_type->id == ZigTypeIdFloat) {
3346 if (rem_kind == RemKindRem) {
3347 return LLVMBuildFRem(g->builder, val1, val2, "");
3348 } else {
3349 LLVMValueRef a = LLVMBuildFRem(g->builder, val1, val2, "");
3350 LLVMValueRef b = LLVMBuildFAdd(g->builder, a, val2, "");
3351 LLVMValueRef c = LLVMBuildFRem(g->builder, b, val2, "");
3352 LLVMValueRef ltz = LLVMBuildFCmp(g->builder, LLVMRealOLT, val1, zero, "");
3353 return LLVMBuildSelect(g->builder, ltz, c, a, "");
3354 }
3355 } else {
3356 assert(scalar_type->id == ZigTypeIdInt);
3357 if (scalar_type->data.integral.is_signed) {
3358 if (rem_kind == RemKindRem) {
3359 return LLVMBuildSRem(g->builder, val1, val2, "");
3360 } else {
3361 LLVMValueRef a = LLVMBuildSRem(g->builder, val1, val2, "");
3362 LLVMValueRef b = LLVMBuildNSWAdd(g->builder, a, val2, "");
3363 LLVMValueRef c = LLVMBuildSRem(g->builder, b, val2, "");
3364 LLVMValueRef ltz = LLVMBuildICmp(g->builder, LLVMIntSLT, val1, zero, "");
3365 return LLVMBuildSelect(g->builder, ltz, c, a, "");
3366 }
3367 } else {
3368 return LLVMBuildURem(g->builder, val1, val2, "");
3369 }
3370 }
3371
3372}
3373
3374static void gen_shift_rhs_check(CodeGen *g, ZigType *lhs_type, ZigType *rhs_type, LLVMValueRef value) {
3375 // We only check if the rhs value of the shift expression is greater or
3376 // equal to the number of bits of the lhs if it's not a power of two,
3377 // otherwise the check is useful as the allowed values are limited by the
3378 // operand type itself
3379 if (!is_power_of_2(lhs_type->data.integral.bit_count)) {
3380 BigInt bit_count_bi = {0};
3381 bigint_init_unsigned(&bit_count_bi, lhs_type->data.integral.bit_count);
3382 LLVMValueRef bit_count_value = bigint_to_llvm_const(get_llvm_type(g, rhs_type),
3383 &bit_count_bi);
3384
3385 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CheckFail");
3386 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CheckOk");
3387 LLVMValueRef less_than_bit = LLVMBuildICmp(g->builder, LLVMIntULT, value, bit_count_value, "");
3388 if (rhs_type->id == ZigTypeIdVector) {
3389 less_than_bit = ZigLLVMBuildOrReduce(g->builder, less_than_bit);
3390 }
3391 LLVMBuildCondBr(g->builder, less_than_bit, ok_block, fail_block);
3392
3393 LLVMPositionBuilderAtEnd(g->builder, fail_block);
3394 gen_safety_crash(g, PanicMsgIdShxTooBigRhs);
3395
3396 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3397 }
3398}
3399
3400enum Icmp {
3401 NONE,
3402 EQ_ZERO,
3403 NE_ZERO,
3404 LE_ZERO,
3405 EQ_NEG,
3406 GE_ZERO,
3407 EQ_ONE,
3408};
3409
3410static LLVMValueRef add_icmp(CodeGen *g, LLVMValueRef val, Icmp kind) {
3411 switch (kind) {
3412 case NONE:
3413 return val;
3414 case EQ_ZERO: {
3415 LLVMValueRef zero = LLVMConstInt(g->builtin_types.entry_i32->llvm_type, 0, true);
3416 return LLVMBuildICmp(g->builder, LLVMIntEQ, val, zero, "");
3417 }
3418 case NE_ZERO: {
3419 LLVMValueRef zero = LLVMConstInt(g->builtin_types.entry_i32->llvm_type, 0, true);
3420 return LLVMBuildICmp(g->builder, LLVMIntNE, val, zero, "");
3421 }
3422 case LE_ZERO: {
3423 LLVMValueRef zero = LLVMConstInt(g->builtin_types.entry_i32->llvm_type, 0, true);
3424 return LLVMBuildICmp(g->builder, LLVMIntSLE, val, zero, "");
3425 }
3426 case EQ_NEG: {
3427 LLVMValueRef zero = LLVMConstInt(g->builtin_types.entry_i32->llvm_type, -1, true);
3428 return LLVMBuildICmp(g->builder, LLVMIntEQ, val, zero, "");
3429 }
3430 case GE_ZERO: {
3431 LLVMValueRef zero = LLVMConstInt(g->builtin_types.entry_i32->llvm_type, 0, true);
3432 return LLVMBuildICmp(g->builder, LLVMIntSGE, val, zero, "");
3433 }
3434 case EQ_ONE: {
3435 LLVMValueRef zero = LLVMConstInt(g->builtin_types.entry_i32->llvm_type, 1, true);
3436 return LLVMBuildICmp(g->builder, LLVMIntEQ, val, zero, "");
3437 }
3438 default:
3439 zig_unreachable();
3440 }
3441}
3442
3443static LLVMValueRef gen_soft_int_to_float_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) {
3444 // Handle integers of non-pot bitsize by widening them.
3445 const size_t bitsize = operand_type->data.integral.bit_count;
3446 const bool is_signed = operand_type->data.integral.is_signed;
3447 if (bitsize < 32 || !is_power_of_2(bitsize)) {
3448 const size_t wider_bitsize = bitsize < 32 ? 32 : round_to_next_power_of_2(bitsize);
3449 ZigType *wider_type = get_int_type(g, is_signed, wider_bitsize);
3450 value_ref = gen_widen_or_shorten(g, false, operand_type, wider_type, value_ref);
3451 operand_type = wider_type;
3452 }
3453 assert(bitsize <= 128);
3454
3455 const char *int_compiler_rt_type_abbrev = get_compiler_rt_type_abbrev(operand_type);
3456 const char *float_compiler_rt_type_abbrev = get_compiler_rt_type_abbrev(result_type);
3457
3458 char fn_name[64];
3459 if (is_signed) {
3460 snprintf(fn_name, sizeof(fn_name), "__float%si%sf", int_compiler_rt_type_abbrev, float_compiler_rt_type_abbrev);
3461 } else {
3462 snprintf(fn_name, sizeof(fn_name), "__floatun%si%sf", int_compiler_rt_type_abbrev, float_compiler_rt_type_abbrev);
3463 }
3464
3465 int param_count = 1;
3466 LLVMValueRef func_ref;
3467 if ((operand_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) {
3468 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard i128 calling
3469 // convention to adhere to the ABI that LLVM expects compiler-rt to have.
3470 LLVMTypeRef v2i64 = LLVMVectorType(LLVMInt64Type(), 2);
3471 value_ref = LLVMBuildBitCast(g->builder, value_ref, v2i64, "");
3472 func_ref = get_soft_float_fn(g, fn_name, param_count, v2i64, result_type->llvm_type);
3473 } else {
3474 func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, result_type->llvm_type);
3475 }
3476
3477 LLVMValueRef params[1] = {value_ref};
3478 return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, "");
3479}
3480
3481static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) {
3482 // Handle integers of non-pot bitsize by truncating a sufficiently wide pot integer
3483 const size_t bitsize = result_type->data.integral.bit_count;
3484 const bool is_signed = result_type->data.integral.is_signed;
3485 ZigType * wider_type = result_type;
3486 if (bitsize < 32 || !is_power_of_2(bitsize)) {
3487 const size_t wider_bitsize = bitsize < 32 ? 32 : round_to_next_power_of_2(bitsize);
3488 wider_type = get_int_type(g, is_signed, wider_bitsize);
3489 }
3490 assert(bitsize <= 128);
3491
3492 const char *float_compiler_rt_type_abbrev = get_compiler_rt_type_abbrev(operand_type);
3493 const char *int_compiler_rt_type_abbrev = get_compiler_rt_type_abbrev(wider_type);
3494
3495 char fn_name[64];
3496 if (is_signed) {
3497 snprintf(fn_name, sizeof(fn_name), "__fix%sf%si", float_compiler_rt_type_abbrev, int_compiler_rt_type_abbrev);
3498 } else {
3499 snprintf(fn_name, sizeof(fn_name), "__fixuns%sf%si", float_compiler_rt_type_abbrev, int_compiler_rt_type_abbrev);
3500 }
3501
3502 int param_count = 1;
3503 LLVMValueRef func_ref;
3504 if ((wider_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) {
3505 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard i128 calling
3506 // convention to adhere to the ABI that LLVM expects compiler-rt to have.
3507 LLVMTypeRef v2i64 = LLVMVectorType(LLVMInt64Type(), 2);
3508 func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, v2i64);
3509 } else {
3510 func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, wider_type->llvm_type);
3511 }
3512
3513 LLVMValueRef params[1] = {value_ref};
3514 LLVMValueRef result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, "");
3515
3516 if ((wider_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) {
3517 result = LLVMBuildBitCast(g->builder, result, wider_type->llvm_type, "");
3518 }
3519
3520 // Handle integers of non-pot bitsize by shortening them on the output
3521 if (result_type != wider_type) {
3522 result = gen_widen_or_shorten(g, false, wider_type, result_type, result);
3523 }
3524
3525 return result;
3526}
3527
3528static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LLVMValueRef op2_value, ZigType *operand_type, IrBinOp op_id) {
3529 uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0;
3530
3531 int param_count = 2;
3532
3533 ZigType *operand_scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
3534 LLVMTypeRef return_scalar_type = operand_scalar_type->llvm_type;
3535 const char *compiler_rt_type_abbrev = get_compiler_rt_type_abbrev(operand_scalar_type);
3536 const char *math_float_prefix = libc_float_prefix(g, operand_scalar_type);
3537 const char *math_float_suffix = libc_float_suffix(g, operand_scalar_type);
3538
3539 char fn_name[64];
3540 Icmp res_icmp = NONE;
3541 switch (op_id) {
3542 case IrBinOpInvalid:
3543 case IrBinOpArrayCat:
3544 case IrBinOpArrayMult:
3545 case IrBinOpRemUnspecified:
3546 case IrBinOpBitShiftLeftLossy:
3547 case IrBinOpBitShiftLeftExact:
3548 case IrBinOpBitShiftRightLossy:
3549 case IrBinOpBitShiftRightExact:
3550 case IrBinOpBoolOr:
3551 case IrBinOpBoolAnd:
3552 case IrBinOpMultWrap:
3553 case IrBinOpAddWrap:
3554 case IrBinOpSubWrap:
3555 case IrBinOpBinOr:
3556 case IrBinOpBinXor:
3557 case IrBinOpBinAnd:
3558 case IrBinOpAddSat:
3559 case IrBinOpSubSat:
3560 case IrBinOpMultSat:
3561 case IrBinOpShlSat:
3562 zig_unreachable();
3563 case IrBinOpCmpEq:
3564 return_scalar_type = g->builtin_types.entry_i32->llvm_type;
3565 snprintf(fn_name, sizeof(fn_name), "__eq%sf2", compiler_rt_type_abbrev);
3566 res_icmp = EQ_ZERO;
3567 break;
3568 case IrBinOpCmpNotEq:
3569 return_scalar_type = g->builtin_types.entry_i32->llvm_type;
3570 snprintf(fn_name, sizeof(fn_name), "__ne%sf2", compiler_rt_type_abbrev);
3571 res_icmp = NE_ZERO;
3572 break;
3573 case IrBinOpCmpLessOrEq:
3574 return_scalar_type = g->builtin_types.entry_i32->llvm_type;
3575 snprintf(fn_name, sizeof(fn_name), "__le%sf2", compiler_rt_type_abbrev);
3576 res_icmp = LE_ZERO;
3577 break;
3578 case IrBinOpCmpLessThan:
3579 return_scalar_type = g->builtin_types.entry_i32->llvm_type;
3580 snprintf(fn_name, sizeof(fn_name), "__le%sf2", compiler_rt_type_abbrev);
3581 res_icmp = EQ_NEG;
3582 break;
3583 case IrBinOpCmpGreaterOrEq:
3584 return_scalar_type = g->builtin_types.entry_i32->llvm_type;
3585 snprintf(fn_name, sizeof(fn_name), "__ge%sf2", compiler_rt_type_abbrev);
3586 res_icmp = GE_ZERO;
3587 break;
3588 case IrBinOpCmpGreaterThan:
3589 return_scalar_type = g->builtin_types.entry_i32->llvm_type;
3590 snprintf(fn_name, sizeof(fn_name), "__ge%sf2", compiler_rt_type_abbrev);
3591 res_icmp = EQ_ONE;
3592 break;
3593 case IrBinOpMax:
3594 snprintf(fn_name, sizeof(fn_name), "%sfmax%s", math_float_prefix, math_float_suffix);
3595 break;
3596 case IrBinOpMin:
3597 snprintf(fn_name, sizeof(fn_name), "%sfmin%s", math_float_prefix, math_float_suffix);
3598 break;
3599 case IrBinOpMult:
3600 snprintf(fn_name, sizeof(fn_name), "__mul%sf3", compiler_rt_type_abbrev);
3601 break;
3602 case IrBinOpAdd:
3603 snprintf(fn_name, sizeof(fn_name), "__add%sf3", compiler_rt_type_abbrev);
3604 break;
3605 case IrBinOpSub:
3606 snprintf(fn_name, sizeof(fn_name), "__sub%sf3", compiler_rt_type_abbrev);
3607 break;
3608 case IrBinOpDivUnspecified:
3609 case IrBinOpDivExact:
3610 case IrBinOpDivTrunc:
3611 case IrBinOpDivFloor:
3612 snprintf(fn_name, sizeof(fn_name), "__div%sf3", compiler_rt_type_abbrev);
3613 break;
3614 case IrBinOpRemRem:
3615 case IrBinOpRemMod:
3616 snprintf(fn_name, sizeof(fn_name), "%sfmod%s", math_float_prefix, math_float_suffix);
3617 break;
3618 default:
3619 zig_unreachable();
3620 }
3621
3622 LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, param_count, operand_scalar_type->llvm_type, return_scalar_type);
3623
3624 LLVMValueRef result;
3625 if (vector_len == 0) {
3626 LLVMValueRef params[2] = {op1_value, op2_value};
3627 result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, "");
3628 result = add_icmp(g, result, res_icmp);
3629 } else {
3630 ZigType *alloca_ty = operand_type;
3631 if (res_icmp != NONE) alloca_ty = get_vector_type(g, vector_len, g->builtin_types.entry_bool);
3632 result = LLVMGetUndef(alloca_ty->llvm_type);
3633
3634 LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type;
3635 for (uint32_t i = 0; i < vector_len; i++) {
3636 LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false);
3637 LLVMValueRef params[2] = {
3638 LLVMBuildExtractElement(g->builder, op1_value, index_value, ""),
3639 LLVMBuildExtractElement(g->builder, op2_value, index_value, ""),
3640 };
3641 LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, "");
3642 call_result = add_icmp(g, call_result, res_icmp);
3643 result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, "");
3644 }
3645 }
3646
3647 // Some operations are implemented as compound ops and require us to perform some
3648 // more operations before we obtain the final result
3649 switch (op_id) {
3650 case IrBinOpDivTrunc:
3651 return gen_float_un_op(g, result, operand_type, BuiltinFnIdTrunc);
3652 case IrBinOpDivFloor:
3653 return gen_float_un_op(g, result, operand_type, BuiltinFnIdFloor);
3654 case IrBinOpRemMod:
3655 {
3656 LLVMValueRef b = gen_soft_float_bin_op(g, result, op2_value, operand_type, IrBinOpAdd);
3657 LLVMValueRef wrapped_result = gen_soft_float_bin_op(g, b, op2_value, operand_type, IrBinOpRemRem);
3658 LLVMValueRef zero = LLVMConstNull(operand_type->llvm_type);
3659 LLVMValueRef ltz = gen_soft_float_bin_op(g, op1_value, zero, operand_type, IrBinOpCmpLessThan);
3660
3661 return LLVMBuildSelect(g->builder, ltz, wrapped_result, result, "");
3662 }
3663 case IrBinOpDivExact:
3664 {
3665 LLVMValueRef floored = gen_float_un_op(g, result, operand_type, BuiltinFnIdFloor);
3666 LLVMValueRef ok_bit = gen_soft_float_bin_op(g, result, floored, operand_type, IrBinOpCmpEq);
3667 if (vector_len != 0) {
3668 ok_bit = ZigLLVMBuildAndReduce(g->builder, ok_bit);
3669 }
3670
3671 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactOk");
3672 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactFail");
3673 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
3674
3675 LLVMPositionBuilderAtEnd(g->builder, fail_block);
3676 gen_safety_crash(g, PanicMsgIdExactDivisionRemainder);
3677
3678 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3679 }
3680 return result;
3681 default:
3682 return result;
3683 }
3684 zig_unreachable();
3685}
3686
3687static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable,
3688 Stage1AirInstBinOp *bin_op_instruction)
3689{
3690 IrBinOp op_id = bin_op_instruction->op_id;
3691 Stage1AirInst *op1 = bin_op_instruction->op1;
3692 Stage1AirInst *op2 = bin_op_instruction->op2;
3693
3694 ZigType *operand_type = op1->value->type;
3695 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
3696 if ((scalar_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) ||
3697 (scalar_type == g->builtin_types.entry_f128 && !target_long_double_is_f128(g->zig_target)) ||
3698 (scalar_type == g->builtin_types.entry_f16 && !target_is_arm(g->zig_target))) {
3699 // LLVM incorrectly lowers the soft float calls for f128 as if they operated on `long double`.
3700 // On some targets this will be incorrect, so we manually lower the call ourselves.
3701 LLVMValueRef op1_value = ir_llvm_value(g, op1);
3702 LLVMValueRef op2_value = ir_llvm_value(g, op2);
3703 return gen_soft_float_bin_op(g, op1_value, op2_value, operand_type, op_id);
3704 }
3705
3706
3707 bool want_runtime_safety = bin_op_instruction->safety_check_on &&
3708 ir_want_runtime_safety(g, &bin_op_instruction->base);
3709
3710 LLVMValueRef op1_value = ir_llvm_value(g, op1);
3711 LLVMValueRef op2_value = ir_llvm_value(g, op2);
3712
3713 switch (op_id) {
3714 case IrBinOpInvalid:
3715 case IrBinOpArrayCat:
3716 case IrBinOpArrayMult:
3717 case IrBinOpRemUnspecified:
3718 zig_unreachable();
3719 case IrBinOpBoolOr:
3720 return LLVMBuildOr(g->builder, op1_value, op2_value, "");
3721 case IrBinOpBoolAnd:
3722 return LLVMBuildAnd(g->builder, op1_value, op2_value, "");
3723 case IrBinOpCmpEq:
3724 case IrBinOpCmpNotEq:
3725 case IrBinOpCmpLessThan:
3726 case IrBinOpCmpGreaterThan:
3727 case IrBinOpCmpLessOrEq:
3728 case IrBinOpCmpGreaterOrEq:
3729 if (scalar_type->id == ZigTypeIdFloat) {
3730 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
3731 LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id);
3732 return LLVMBuildFCmp(g->builder, pred, op1_value, op2_value, "");
3733 } else if (scalar_type->id == ZigTypeIdInt) {
3734 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, scalar_type->data.integral.is_signed);
3735 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
3736 } else if (scalar_type->id == ZigTypeIdEnum ||
3737 scalar_type->id == ZigTypeIdErrorSet ||
3738 scalar_type->id == ZigTypeIdBool ||
3739 get_codegen_ptr_type_bail(g, scalar_type) != nullptr)
3740 {
3741 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
3742 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
3743 } else {
3744 zig_unreachable();
3745 }
3746 case IrBinOpMult:
3747 case IrBinOpMultWrap:
3748 case IrBinOpAdd:
3749 case IrBinOpAddWrap:
3750 case IrBinOpSub:
3751 case IrBinOpSubWrap: {
3752 bool is_wrapping = (op_id == IrBinOpSubWrap || op_id == IrBinOpAddWrap || op_id == IrBinOpMultWrap);
3753 AddSubMul add_sub_mul =
3754 op_id == IrBinOpAdd || op_id == IrBinOpAddWrap ? AddSubMulAdd :
3755 op_id == IrBinOpSub || op_id == IrBinOpSubWrap ? AddSubMulSub :
3756 AddSubMulMul;
3757
3758 if (scalar_type->id == ZigTypeIdPointer) {
3759 LLVMValueRef subscript_value;
3760 if (operand_type->id == ZigTypeIdVector)
3761 zig_panic("TODO: Implement vector operations on pointers.");
3762
3763 switch (add_sub_mul) {
3764 case AddSubMulAdd:
3765 subscript_value = op2_value;
3766 break;
3767 case AddSubMulSub:
3768 subscript_value = LLVMBuildNeg(g->builder, op2_value, "");
3769 break;
3770 case AddSubMulMul:
3771 zig_unreachable();
3772 }
3773
3774 // TODO runtime safety
3775 LLVMTypeRef elem_llvm_ty = get_llvm_type(g, scalar_type->data.pointer.child_type);
3776 return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, op1_value,
3777 &subscript_value, 1, "");
3778 } else if (scalar_type->id == ZigTypeIdFloat) {
3779 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
3780 return float_op[add_sub_mul](g->builder, op1_value, op2_value, "");
3781 } else if (scalar_type->id == ZigTypeIdInt) {
3782 if (is_wrapping) {
3783 return wrap_op[add_sub_mul](g->builder, op1_value, op2_value, "");
3784 } else if (want_runtime_safety) {
3785 return gen_overflow_op(g, operand_type, add_sub_mul, op1_value, op2_value);
3786 } else if (scalar_type->data.integral.is_signed) {
3787 return signed_op[add_sub_mul](g->builder, op1_value, op2_value, "");
3788 } else {
3789 return unsigned_op[add_sub_mul](g->builder, op1_value, op2_value, "");
3790 }
3791 } else {
3792 zig_unreachable();
3793 }
3794 }
3795 case IrBinOpBinOr:
3796 return LLVMBuildOr(g->builder, op1_value, op2_value, "");
3797 case IrBinOpBinXor:
3798 return LLVMBuildXor(g->builder, op1_value, op2_value, "");
3799 case IrBinOpBinAnd:
3800 return LLVMBuildAnd(g->builder, op1_value, op2_value, "");
3801 case IrBinOpBitShiftLeftLossy:
3802 case IrBinOpBitShiftLeftExact:
3803 {
3804 assert(scalar_type->id == ZigTypeIdInt);
3805 LLVMValueRef op2_casted = LLVMBuildZExt(g->builder, op2_value,
3806 LLVMTypeOf(op1_value), "");
3807
3808 if (want_runtime_safety) {
3809 gen_shift_rhs_check(g, scalar_type, op2->value->type, op2_value);
3810 }
3811
3812 bool is_sloppy = (op_id == IrBinOpBitShiftLeftLossy);
3813 if (is_sloppy) {
3814 return LLVMBuildShl(g->builder, op1_value, op2_casted, "");
3815 } else if (want_runtime_safety) {
3816 return gen_overflow_shl_op(g, operand_type, op1_value, op2_casted);
3817 } else if (scalar_type->data.integral.is_signed) {
3818 return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_casted, "");
3819 } else {
3820 return ZigLLVMBuildNUWShl(g->builder, op1_value, op2_casted, "");
3821 }
3822 }
3823 case IrBinOpBitShiftRightLossy:
3824 case IrBinOpBitShiftRightExact:
3825 {
3826 assert(scalar_type->id == ZigTypeIdInt);
3827 LLVMValueRef op2_casted = LLVMBuildZExt(g->builder, op2_value,
3828 LLVMTypeOf(op1_value), "");
3829
3830 if (want_runtime_safety) {
3831 gen_shift_rhs_check(g, scalar_type, op2->value->type, op2_value);
3832 }
3833
3834 bool is_sloppy = (op_id == IrBinOpBitShiftRightLossy);
3835 if (is_sloppy) {
3836 if (scalar_type->data.integral.is_signed) {
3837 return LLVMBuildAShr(g->builder, op1_value, op2_casted, "");
3838 } else {
3839 return LLVMBuildLShr(g->builder, op1_value, op2_casted, "");
3840 }
3841 } else if (want_runtime_safety) {
3842 return gen_overflow_shr_op(g, operand_type, op1_value, op2_casted);
3843 } else if (scalar_type->data.integral.is_signed) {
3844 return ZigLLVMBuildAShrExact(g->builder, op1_value, op2_casted, "");
3845 } else {
3846 return ZigLLVMBuildLShrExact(g->builder, op1_value, op2_casted, "");
3847 }
3848 }
3849 case IrBinOpDivUnspecified:
3850 return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
3851 op1_value, op2_value, operand_type, DivKindFloat);
3852 case IrBinOpDivExact:
3853 return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
3854 op1_value, op2_value, operand_type, DivKindExact);
3855 case IrBinOpDivTrunc:
3856 return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
3857 op1_value, op2_value, operand_type, DivKindTrunc);
3858 case IrBinOpDivFloor:
3859 return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
3860 op1_value, op2_value, operand_type, DivKindFloor);
3861 case IrBinOpRemRem:
3862 return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
3863 op1_value, op2_value, operand_type, RemKindRem);
3864 case IrBinOpRemMod:
3865 return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
3866 op1_value, op2_value, operand_type, RemKindMod);
3867 case IrBinOpMax:
3868 if (scalar_type->id == ZigTypeIdFloat) {
3869 return ZigLLVMBuildMaxNum(g->builder, op1_value, op2_value, "");
3870 } else if (scalar_type->id == ZigTypeIdInt) {
3871 if (scalar_type->data.integral.is_signed) {
3872 return ZigLLVMBuildSMax(g->builder, op1_value, op2_value, "");
3873 } else {
3874 return ZigLLVMBuildUMax(g->builder, op1_value, op2_value, "");
3875 }
3876 } else {
3877 zig_unreachable();
3878 }
3879 case IrBinOpMin:
3880 if (scalar_type->id == ZigTypeIdFloat) {
3881 return ZigLLVMBuildMinNum(g->builder, op1_value, op2_value, "");
3882 } else if (scalar_type->id == ZigTypeIdInt) {
3883 if (scalar_type->data.integral.is_signed) {
3884 return ZigLLVMBuildSMin(g->builder, op1_value, op2_value, "");
3885 } else {
3886 return ZigLLVMBuildUMin(g->builder, op1_value, op2_value, "");
3887 }
3888 } else {
3889 zig_unreachable();
3890 }
3891 case IrBinOpAddSat:
3892 if (scalar_type->id == ZigTypeIdInt) {
3893 if (scalar_type->data.integral.is_signed) {
3894 return ZigLLVMBuildSAddSat(g->builder, op1_value, op2_value, "");
3895 } else {
3896 return ZigLLVMBuildUAddSat(g->builder, op1_value, op2_value, "");
3897 }
3898 } else {
3899 zig_unreachable();
3900 }
3901 case IrBinOpSubSat:
3902 if (scalar_type->id == ZigTypeIdInt) {
3903 if (scalar_type->data.integral.is_signed) {
3904 return ZigLLVMBuildSSubSat(g->builder, op1_value, op2_value, "");
3905 } else {
3906 return ZigLLVMBuildUSubSat(g->builder, op1_value, op2_value, "");
3907 }
3908 } else {
3909 zig_unreachable();
3910 }
3911 case IrBinOpMultSat:
3912 if (scalar_type->id == ZigTypeIdInt) {
3913 if (scalar_type->data.integral.is_signed) {
3914 return ZigLLVMBuildSMulFixSat(g->builder, op1_value, op2_value, "");
3915 } else {
3916 return ZigLLVMBuildUMulFixSat(g->builder, op1_value, op2_value, "");
3917 }
3918 } else {
3919 zig_unreachable();
3920 }
3921 case IrBinOpShlSat: {
3922 if (scalar_type->id != ZigTypeIdInt) {
3923 zig_unreachable();
3924 }
3925 LLVMValueRef result = scalar_type->data.integral.is_signed ?
3926 ZigLLVMBuildSShlSat(g->builder, op1_value, op2_value, "") :
3927 ZigLLVMBuildUShlSat(g->builder, op1_value, op2_value, "");
3928 // LLVM langref says "If b is (statically or dynamically) equal to or
3929 // larger than the integer bit width of the arguments, the result is a
3930 // poison value."
3931 // However Zig semantics says that saturating shift left can never produce
3932 // undefined; instead it saturates.
3933 LLVMTypeRef lhs_scalar_llvm_ty = get_llvm_type(g, scalar_type);
3934 LLVMValueRef bits = LLVMConstInt(lhs_scalar_llvm_ty,
3935 scalar_type->data.integral.bit_count, false);
3936 LLVMValueRef lhs_max = LLVMConstAllOnes(lhs_scalar_llvm_ty);
3937 if (operand_type->id == ZigTypeIdVector) {
3938 uint64_t vec_len = operand_type->data.vector.len;
3939 LLVMValueRef bits_vec = LLVMBuildVectorSplat(g->builder, vec_len, bits, "");
3940 LLVMValueRef lhs_max_vec = LLVMBuildVectorSplat(g->builder, vec_len, lhs_max, "");
3941 LLVMValueRef in_range = LLVMBuildICmp(g->builder, LLVMIntULT, op2_value, bits_vec, "");
3942 return LLVMBuildSelect(g->builder, in_range, result, lhs_max_vec, "");
3943 } else {
3944 LLVMValueRef in_range = LLVMBuildICmp(g->builder, LLVMIntULT, op2_value, bits, "");
3945 return LLVMBuildSelect(g->builder, in_range, result, lhs_max, "");
3946 }
3947 }
3948 }
3949 zig_unreachable();
3950}
3951
3952static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *int_type, LLVMValueRef target_val) {
3953 assert(err_set_type->id == ZigTypeIdErrorSet);
3954
3955 if (type_is_global_error_set(err_set_type)) {
3956 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, int_type));
3957 LLVMValueRef neq_zero_bit = LLVMBuildICmp(g->builder, LLVMIntNE, target_val, zero, "");
3958 LLVMValueRef ok_bit;
3959
3960 BigInt biggest_possible_err_val = {0};
3961 eval_min_max_value_int(g, int_type, &biggest_possible_err_val, true);
3962
3963 if (bigint_fits_in_bits(&biggest_possible_err_val, 64, false) &&
3964 bigint_as_usize(&biggest_possible_err_val) < g->errors_by_index.length)
3965 {
3966 ok_bit = neq_zero_bit;
3967 } else {
3968 LLVMValueRef error_value_count = LLVMConstInt(get_llvm_type(g, int_type), g->errors_by_index.length, false);
3969 LLVMValueRef in_bounds_bit = LLVMBuildICmp(g->builder, LLVMIntULT, target_val, error_value_count, "");
3970 ok_bit = LLVMBuildAnd(g->builder, neq_zero_bit, in_bounds_bit, "");
3971 }
3972
3973 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "IntToErrOk");
3974 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "IntToErrFail");
3975
3976 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
3977
3978 LLVMPositionBuilderAtEnd(g->builder, fail_block);
3979 gen_safety_crash(g, PanicMsgIdInvalidErrorCode);
3980
3981 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3982 } else {
3983 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "IntToErrOk");
3984 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "IntToErrFail");
3985
3986 uint32_t err_count = err_set_type->data.error_set.err_count;
3987 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, target_val, fail_block, err_count);
3988 for (uint32_t i = 0; i < err_count; i += 1) {
3989 LLVMValueRef case_value = LLVMConstInt(get_llvm_type(g, g->err_tag_type),
3990 err_set_type->data.error_set.errors[i]->value, false);
3991 LLVMAddCase(switch_instr, case_value, ok_block);
3992 }
3993
3994 LLVMPositionBuilderAtEnd(g->builder, fail_block);
3995 gen_safety_crash(g, PanicMsgIdInvalidErrorCode);
3996
3997 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3998 }
3999}
4000
4001static LLVMValueRef ir_render_cast(CodeGen *g, Stage1Air *executable,
4002 Stage1AirInstCast *cast_instruction)
4003{
4004 Error err;
4005 ZigType *actual_type = cast_instruction->value->value->type;
4006 ZigType *wanted_type = cast_instruction->base.value->type;
4007 bool wanted_type_has_bits;
4008 if ((err = type_has_bits2(g, wanted_type, &wanted_type_has_bits)))
4009 codegen_report_errors_and_exit(g);
4010 if (!wanted_type_has_bits)
4011 return nullptr;
4012 LLVMValueRef expr_val = ir_llvm_value(g, cast_instruction->value);
4013 ir_assert(expr_val, &cast_instruction->base);
4014
4015 switch (cast_instruction->cast_op) {
4016 case CastOpNoCast:
4017 case CastOpNumLitToConcrete:
4018 zig_unreachable();
4019 case CastOpNoop:
4020 if (actual_type->id == ZigTypeIdPointer && wanted_type->id == ZigTypeIdPointer &&
4021 actual_type->data.pointer.child_type->id == ZigTypeIdArray &&
4022 wanted_type->data.pointer.child_type->id == ZigTypeIdArray)
4023 {
4024 return LLVMBuildBitCast(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
4025 } else {
4026 return expr_val;
4027 }
4028 case CastOpIntToFloat:
4029 assert(actual_type->id == ZigTypeIdInt);
4030 {
4031 if ((wanted_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) ||
4032 (wanted_type == g->builtin_types.entry_f128 && !target_long_double_is_f128(g->zig_target)) ||
4033 (wanted_type == g->builtin_types.entry_f16 && !target_is_arm(g->zig_target))) {
4034 return gen_soft_int_to_float_op(g, expr_val, actual_type, wanted_type);
4035 } else {
4036 if (actual_type->data.integral.is_signed) {
4037 return LLVMBuildSIToFP(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
4038 } else {
4039 return LLVMBuildUIToFP(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
4040 }
4041 }
4042 }
4043 case CastOpFloatToInt: {
4044 assert(wanted_type->id == ZigTypeIdInt);
4045 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &cast_instruction->base));
4046
4047 bool want_safety = ir_want_runtime_safety(g, &cast_instruction->base);
4048
4049 LLVMValueRef result;
4050 if ((actual_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) ||
4051 (actual_type == g->builtin_types.entry_f128 && !target_long_double_is_f128(g->zig_target)) ||
4052 (actual_type == g->builtin_types.entry_f16 && !target_is_arm(g->zig_target))) {
4053 result = gen_soft_float_to_int_op(g, expr_val, actual_type, wanted_type);
4054 } else {
4055 if (wanted_type->data.integral.is_signed) {
4056 result = LLVMBuildFPToSI(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
4057 } else {
4058 result = LLVMBuildFPToUI(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
4059 }
4060 }
4061
4062 if (want_safety) {
4063 LLVMValueRef back_to_float;
4064 if ((actual_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) ||
4065 (actual_type == g->builtin_types.entry_f128 && !target_long_double_is_f128(g->zig_target))) {
4066 back_to_float = gen_soft_int_to_float_op(g, result, wanted_type, actual_type);
4067 } else {
4068 if (wanted_type->data.integral.is_signed) {
4069 back_to_float = LLVMBuildSIToFP(g->builder, result, LLVMTypeOf(expr_val), "");
4070 } else {
4071 back_to_float = LLVMBuildUIToFP(g->builder, result, LLVMTypeOf(expr_val), "");
4072 }
4073 }
4074 LLVMValueRef difference = LLVMBuildFSub(g->builder, expr_val, back_to_float, "");
4075 LLVMValueRef one_pos = LLVMConstReal(LLVMTypeOf(expr_val), 1.0f);
4076 LLVMValueRef one_neg = LLVMConstReal(LLVMTypeOf(expr_val), -1.0f);
4077 LLVMValueRef ok_bit_pos = LLVMBuildFCmp(g->builder, LLVMRealOLT, difference, one_pos, "");
4078 LLVMValueRef ok_bit_neg = LLVMBuildFCmp(g->builder, LLVMRealOGT, difference, one_neg, "");
4079 LLVMValueRef ok_bit = LLVMBuildAnd(g->builder, ok_bit_pos, ok_bit_neg, "");
4080 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "FloatCheckOk");
4081 LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "FloatCheckFail");
4082 LLVMBuildCondBr(g->builder, ok_bit, ok_block, bad_block);
4083 LLVMPositionBuilderAtEnd(g->builder, bad_block);
4084 gen_safety_crash(g, PanicMsgIdFloatToInt);
4085 LLVMPositionBuilderAtEnd(g->builder, ok_block);
4086 }
4087 return result;
4088 }
4089 case CastOpBoolToInt:
4090 assert(wanted_type->id == ZigTypeIdInt);
4091 assert(actual_type->id == ZigTypeIdBool);
4092 return LLVMBuildZExt(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
4093 case CastOpErrSet:
4094 if (ir_want_runtime_safety(g, &cast_instruction->base)) {
4095 add_error_range_check(g, wanted_type, g->err_tag_type, expr_val);
4096 }
4097 return expr_val;
4098 case CastOpBitCast:
4099 return LLVMBuildBitCast(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
4100 }
4101 zig_unreachable();
4102}
4103
4104static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, Stage1Air *executable,
4105 Stage1AirInstPtrOfArrayToSlice *instruction)
4106{
4107 ZigType *actual_type = instruction->operand->value->type;
4108 ZigType *slice_type = instruction->base.value->type;
4109 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
4110 size_t ptr_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index;
4111 size_t len_index = slice_type->data.structure.fields[slice_len_index]->gen_index;
4112
4113 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
4114
4115 assert(actual_type->id == ZigTypeIdPointer);
4116 ZigType *array_type = actual_type->data.pointer.child_type;
4117 assert(array_type->id == ZigTypeIdArray);
4118
4119 if (type_has_bits(g, actual_type)) {
4120 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, slice_type),
4121 result_loc, ptr_index, "");
4122 LLVMValueRef indices[] = {
4123 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
4124 LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false),
4125 };
4126 LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);
4127 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder,
4128 get_llvm_type(g, array_type), expr_val, indices, 2, "");
4129 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
4130 } else if (ir_want_runtime_safety(g, &instruction->base) && ptr_index != SIZE_MAX) {
4131 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, slice_type), result_loc, ptr_index, "");
4132 gen_undef_init(g, slice_ptr_type, slice_ptr_type, ptr_field_ptr);
4133 }
4134
4135 LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, slice_type), result_loc, len_index, "");
4136 LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
4137 array_type->data.array.len, false);
4138 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
4139
4140 return result_loc;
4141}
4142
4143static LLVMValueRef ir_render_ptr_cast(CodeGen *g, Stage1Air *executable,
4144 Stage1AirInstPtrCast *instruction)
4145{
4146 ZigType *wanted_type = instruction->base.value->type;
4147 if (!type_has_bits(g, wanted_type)) {
4148 return nullptr;
4149 }
4150 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
4151 LLVMValueRef result_ptr = LLVMBuildBitCast(g->builder, ptr, get_llvm_type(g, wanted_type), "");
4152 bool want_safety_check = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
4153 if (!want_safety_check || ptr_allows_addr_zero(wanted_type))
4154 return result_ptr;
4155
4156 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(result_ptr));
4157 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntNE, result_ptr, zero, "");
4158 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastFail");
4159 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastOk");
4160 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
4161
4162 LLVMPositionBuilderAtEnd(g->builder, fail_block);
4163 gen_safety_crash(g, PanicMsgIdPtrCastNull);
4164
4165 LLVMPositionBuilderAtEnd(g->builder, ok_block);
4166 return result_ptr;
4167}
4168
4169static LLVMValueRef ir_render_bit_cast(CodeGen *g, Stage1Air *executable,
4170 Stage1AirInstBitCast *instruction)
4171{
4172 ZigType *wanted_type = instruction->base.value->type;
4173 ZigType *actual_type = instruction->operand->value->type;
4174 LLVMValueRef value = ir_llvm_value(g, instruction->operand);
4175
4176 bool wanted_is_ptr = handle_is_ptr(g, wanted_type);
4177 bool actual_is_ptr = handle_is_ptr(g, actual_type);
4178 if (wanted_is_ptr == actual_is_ptr) {
4179 // We either bitcast the value directly or bitcast the pointer which does a pointer cast
4180 LLVMTypeRef wanted_type_ref = wanted_is_ptr ?
4181 LLVMPointerType(get_llvm_type(g, wanted_type), 0) : get_llvm_type(g, wanted_type);
4182 return LLVMBuildBitCast(g->builder, value, wanted_type_ref, "");
4183 } else if (actual_is_ptr) {
4184 // A scalar is wanted but we got a pointer
4185 LLVMTypeRef wanted_elem_type_ref = get_llvm_type(g, wanted_type);
4186 LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, value,
4187 LLVMPointerType(wanted_elem_type_ref, 0), "");
4188 uint32_t alignment = get_abi_alignment(g, actual_type);
4189 return gen_load_untyped(g, wanted_elem_type_ref, bitcasted_ptr, alignment, false, "");
4190 } else {
4191 // A pointer is wanted but we got a scalar
4192 assert(actual_type->id == ZigTypeIdPointer);
4193 LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, wanted_type), 0);
4194 return LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, "");
4195 }
4196}
4197
4198static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, Stage1Air *executable,
4199 Stage1AirInstWidenOrShorten *instruction)
4200{
4201 ZigType *actual_type = instruction->target->value->type;
4202 // TODO instead of this logic, use the Noop instruction to change the type from
4203 // enum_tag to the underlying int type
4204 ZigType *int_type;
4205 if (actual_type->id == ZigTypeIdEnum) {
4206 int_type = actual_type->data.enumeration.tag_int_type;
4207 } else {
4208 int_type = actual_type;
4209 }
4210 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
4211 return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), int_type,
4212 instruction->base.value->type, target_val);
4213}
4214
4215static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, Stage1Air *executable, Stage1AirInstIntToPtr *instruction) {
4216 ZigType *wanted_type = instruction->base.value->type;
4217 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
4218 const uint32_t align_bytes = get_ptr_align(g, wanted_type);
4219
4220 if (ir_want_runtime_safety(g, &instruction->base)) {
4221 ZigType *usize = g->builtin_types.entry_usize;
4222 LLVMValueRef zero = LLVMConstNull(usize->llvm_type);
4223
4224 if (!ptr_allows_addr_zero(wanted_type)) {
4225 LLVMValueRef is_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, target_val, zero, "");
4226 LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrToIntBad");
4227 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrToIntOk");
4228 LLVMBuildCondBr(g->builder, is_zero_bit, bad_block, ok_block);
4229
4230 LLVMPositionBuilderAtEnd(g->builder, bad_block);
4231 gen_safety_crash(g, PanicMsgIdPtrCastNull);
4232
4233 LLVMPositionBuilderAtEnd(g->builder, ok_block);
4234 }
4235
4236 if (align_bytes > 1) {
4237 LLVMValueRef alignment_minus_1 = LLVMConstInt(usize->llvm_type, align_bytes - 1, false);
4238 LLVMValueRef anded_val = LLVMBuildAnd(g->builder, target_val, alignment_minus_1, "");
4239 LLVMValueRef is_ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, anded_val, zero, "");
4240 LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrToIntAlignBad");
4241 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrToIntAlignOk");
4242 LLVMBuildCondBr(g->builder, is_ok_bit, ok_block, bad_block);
4243
4244 LLVMPositionBuilderAtEnd(g->builder, bad_block);
4245 gen_safety_crash(g, PanicMsgIdIncorrectAlignment);
4246
4247 LLVMPositionBuilderAtEnd(g->builder, ok_block);
4248 }
4249 }
4250 return LLVMBuildIntToPtr(g->builder, target_val, get_llvm_type(g, wanted_type), "");
4251}
4252
4253static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, Stage1Air *executable, Stage1AirInstPtrToInt *instruction) {
4254 ZigType *wanted_type = instruction->base.value->type;
4255 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
4256 return LLVMBuildPtrToInt(g->builder, target_val, get_llvm_type(g, wanted_type), "");
4257}
4258
4259static LLVMValueRef ir_render_int_to_enum(CodeGen *g, Stage1Air *executable, Stage1AirInstIntToEnum *instruction) {
4260 ZigType *wanted_type = instruction->base.value->type;
4261 assert(wanted_type->id == ZigTypeIdEnum);
4262 ZigType *tag_int_type = wanted_type->data.enumeration.tag_int_type;
4263
4264 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
4265 LLVMValueRef tag_int_value = gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base),
4266 instruction->target->value->type, tag_int_type, target_val);
4267
4268 if (ir_want_runtime_safety(g, &instruction->base) && !wanted_type->data.enumeration.non_exhaustive) {
4269 LLVMBasicBlockRef bad_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadValue");
4270 LLVMBasicBlockRef ok_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "OkValue");
4271 size_t field_count = wanted_type->data.enumeration.src_field_count;
4272 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, tag_int_value, bad_value_block, field_count);
4273
4274 HashMap<BigInt, Buf *, bigint_hash, bigint_eql> occupied_tag_values = {};
4275 occupied_tag_values.init(field_count);
4276
4277 for (size_t field_i = 0; field_i < field_count; field_i += 1) {
4278 TypeEnumField *type_enum_field = &wanted_type->data.enumeration.fields[field_i];
4279
4280 Buf *name = type_enum_field->name;
4281 auto entry = occupied_tag_values.put_unique(type_enum_field->value, name);
4282 if (entry != nullptr) {
4283 continue;
4284 }
4285
4286 LLVMValueRef this_tag_int_value = bigint_to_llvm_const(get_llvm_type(g, tag_int_type),
4287 &type_enum_field->value);
4288 LLVMAddCase(switch_instr, this_tag_int_value, ok_value_block);
4289 }
4290 occupied_tag_values.deinit();
4291 LLVMPositionBuilderAtEnd(g->builder, bad_value_block);
4292 gen_safety_crash(g, PanicMsgIdBadEnumValue);
4293
4294 LLVMPositionBuilderAtEnd(g->builder, ok_value_block);
4295 }
4296 return tag_int_value;
4297}
4298
4299static LLVMValueRef ir_render_int_to_err(CodeGen *g, Stage1Air *executable, Stage1AirInstIntToErr *instruction) {
4300 ZigType *wanted_type = instruction->base.value->type;
4301 assert(wanted_type->id == ZigTypeIdErrorSet);
4302
4303 ZigType *actual_type = instruction->target->value->type;
4304 assert(actual_type->id == ZigTypeIdInt);
4305 assert(!actual_type->data.integral.is_signed);
4306
4307 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
4308
4309 if (ir_want_runtime_safety(g, &instruction->base)) {
4310 add_error_range_check(g, wanted_type, actual_type, target_val);
4311 }
4312
4313 return gen_widen_or_shorten(g, false, actual_type, g->err_tag_type, target_val);
4314}
4315
4316static LLVMValueRef ir_render_err_to_int(CodeGen *g, Stage1Air *executable, Stage1AirInstErrToInt *instruction) {
4317 ZigType *wanted_type = instruction->base.value->type;
4318 assert(wanted_type->id == ZigTypeIdInt);
4319 assert(!wanted_type->data.integral.is_signed);
4320
4321 ZigType *actual_type = instruction->target->value->type;
4322 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
4323
4324 if (actual_type->id == ZigTypeIdErrorSet) {
4325 return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base),
4326 g->err_tag_type, wanted_type, target_val);
4327 } else if (actual_type->id == ZigTypeIdErrorUnion) {
4328 // this should have been a compile time constant
4329 assert(type_has_bits(g, actual_type->data.error_union.err_set_type));
4330
4331 if (!type_has_bits(g, actual_type->data.error_union.payload_type)) {
4332 return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base),
4333 g->err_tag_type, wanted_type, target_val);
4334 } else {
4335 zig_panic("TODO err to int when error union payload type not void");
4336 }
4337 } else {
4338 zig_unreachable();
4339 }
4340}
4341
4342static LLVMValueRef ir_render_unreachable(CodeGen *g, Stage1Air *executable,
4343 Stage1AirInstUnreachable *unreachable_instruction)
4344{
4345 if (ir_want_runtime_safety(g, &unreachable_instruction->base)) {
4346 gen_safety_crash(g, PanicMsgIdUnreachable);
4347 } else {
4348 LLVMBuildUnreachable(g->builder);
4349 }
4350 return nullptr;
4351}
4352
4353static LLVMValueRef ir_render_cond_br(CodeGen *g, Stage1Air *executable,
4354 Stage1AirInstCondBr *cond_br_instruction)
4355{
4356 LLVMBuildCondBr(g->builder,
4357 ir_llvm_value(g, cond_br_instruction->condition),
4358 cond_br_instruction->then_block->llvm_block,
4359 cond_br_instruction->else_block->llvm_block);
4360 return nullptr;
4361}
4362
4363static LLVMValueRef ir_render_br(CodeGen *g, Stage1Air *executable, Stage1AirInstBr *br_instruction) {
4364 LLVMBuildBr(g->builder, br_instruction->dest_block->llvm_block);
4365 return nullptr;
4366}
4367
4368static LLVMValueRef ir_render_binary_not(CodeGen *g, Stage1Air *executable,
4369 Stage1AirInstBinaryNot *inst)
4370{
4371 LLVMValueRef operand = ir_llvm_value(g, inst->operand);
4372 return LLVMBuildNot(g->builder, operand, "");
4373}
4374
4375static LLVMValueRef gen_soft_float_neg(CodeGen *g, ZigType *operand_type, LLVMValueRef operand) {
4376 uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0;
4377 uint16_t num_bits = operand_type->id == ZigTypeIdVector ?
4378 operand_type->data.vector.elem_type->data.floating.bit_count :
4379 operand_type->data.floating.bit_count;
4380
4381 ZigType *iX_type = get_int_type(g, true, num_bits);
4382 LLVMValueRef sign_mask = LLVMConstShl(
4383 LLVMConstInt(iX_type->llvm_type, 1, false),
4384 LLVMConstInt(iX_type->llvm_type, num_bits - 1, false));
4385
4386 LLVMValueRef sign_mask_splat = (vector_len == 0) ? sign_mask :
4387 LLVMBuildVectorSplat(g->builder, vector_len, sign_mask, "");
4388
4389 LLVMValueRef bitcasted_operand = LLVMBuildBitCast(g->builder, operand,
4390 (vector_len == 0) ?
4391 iX_type->llvm_type :
4392 get_vector_type(g, vector_len, iX_type)->llvm_type,
4393 "");
4394
4395 LLVMValueRef result = LLVMBuildXor(g->builder, bitcasted_operand, sign_mask_splat, "");
4396 return LLVMBuildBitCast(g->builder, result, operand_type->llvm_type, "");
4397}
4398
4399static LLVMValueRef gen_negation(CodeGen *g, Stage1AirInst *inst, Stage1AirInst *operand, bool wrapping) {
4400 LLVMValueRef llvm_operand = ir_llvm_value(g, operand);
4401 ZigType *operand_type = operand->value->type;
4402 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ?
4403 operand_type->data.vector.elem_type : operand_type;
4404
4405 if ((scalar_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) ||
4406 (scalar_type == g->builtin_types.entry_f128 && !target_long_double_is_f128(g->zig_target)) ||
4407 (scalar_type == g->builtin_types.entry_f16 && !target_is_arm(g->zig_target))) {
4408 return gen_soft_float_neg(g, operand_type, llvm_operand);
4409 }
4410
4411 if (scalar_type->id == ZigTypeIdFloat) {
4412 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, inst));
4413 return LLVMBuildFNeg(g->builder, llvm_operand, "");
4414 } else if (scalar_type->id == ZigTypeIdInt) {
4415 if (wrapping) {
4416 return LLVMBuildNeg(g->builder, llvm_operand, "");
4417 } else if (ir_want_runtime_safety(g, inst)) {
4418 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(llvm_operand));
4419 return gen_overflow_op(g, operand_type, AddSubMulSub, zero, llvm_operand);
4420 } else if (scalar_type->data.integral.is_signed) {
4421 return LLVMBuildNSWNeg(g->builder, llvm_operand, "");
4422 } else {
4423 zig_unreachable();
4424 }
4425 } else {
4426 zig_unreachable();
4427 }
4428}
4429
4430static LLVMValueRef ir_render_negation(CodeGen *g, Stage1Air *executable,
4431 Stage1AirInstNegation *inst)
4432{
4433 return gen_negation(g, &inst->base, inst->operand, inst->wrapping);
4434}
4435
4436static LLVMValueRef ir_render_bool_not(CodeGen *g, Stage1Air *executable, Stage1AirInstBoolNot *instruction) {
4437 LLVMValueRef value = ir_llvm_value(g, instruction->value);
4438 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(value));
4439 return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, "");
4440}
4441
4442static void render_decl_var(CodeGen *g, ZigVar *var) {
4443 if (!type_has_bits(g, var->var_type))
4444 return;
4445
4446 var->value_ref = ir_llvm_value(g, var->ptr_instruction);
4447 gen_var_debug_decl(g, var);
4448}
4449
4450static LLVMValueRef ir_render_decl_var(CodeGen *g, Stage1Air *executable, Stage1AirInstDeclVar *instruction) {
4451 instruction->var->ptr_instruction = instruction->var_ptr;
4452 instruction->var->did_the_decl_codegen = true;
4453 render_decl_var(g, instruction->var);
4454 return nullptr;
4455}
4456
4457static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable,
4458 Stage1AirInstLoadPtr *instruction)
4459{
4460 ZigType *child_type = instruction->base.value->type;
4461 if (!type_has_bits(g, child_type))
4462 return nullptr;
4463
4464 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
4465 ZigType *ptr_type = instruction->ptr->value->type;
4466 assert(ptr_type->id == ZigTypeIdPointer);
4467
4468 ir_assert(ptr_type->data.pointer.vector_index != VECTOR_INDEX_RUNTIME, &instruction->base);
4469 if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) {
4470 LLVMValueRef index_val = LLVMConstInt(LLVMInt32Type(),
4471 ptr_type->data.pointer.vector_index, false);
4472 uint32_t vec_len = ptr_type->data.pointer.host_int_bytes;
4473 LLVMTypeRef vec_llvm_ty = LLVMVectorType(get_llvm_type(g, child_type), vec_len);
4474 LLVMValueRef loaded_vector = LLVMBuildLoad2(g->builder, vec_llvm_ty, ptr, "");
4475 return LLVMBuildExtractElement(g->builder, loaded_vector, index_val, "");
4476 }
4477
4478 uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;
4479 if (host_int_bytes == 0)
4480 return get_handle_value(g, ptr, child_type, ptr_type);
4481
4482 bool big_endian = g->is_big_endian;
4483
4484 LLVMTypeRef int_ptr_ty = LLVMPointerType(LLVMIntType(host_int_bytes * 8), 0);
4485 LLVMValueRef int_ptr = LLVMBuildBitCast(g->builder, ptr, int_ptr_ty, "");
4486 LLVMValueRef containing_int = gen_load_untyped(g, LLVMIntType(host_int_bytes * 8), int_ptr,
4487 get_ptr_align(g, ptr_type), ptr_type->data.pointer.is_volatile, "");
4488
4489 uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));
4490 ir_assert(host_bit_count == host_int_bytes * 8, &instruction->base);
4491 uint32_t size_in_bits = type_size_bits(g, child_type);
4492
4493 uint32_t bit_offset = ptr_type->data.pointer.bit_offset_in_host;
4494 uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - size_in_bits : bit_offset;
4495
4496 LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
4497 LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");
4498
4499 if (handle_is_ptr(g, child_type)) {
4500 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
4501 LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);
4502 LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, "");
4503 LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, result_loc,
4504 LLVMPointerType(same_size_int, 0), "");
4505 LLVMBuildStore(g->builder, truncated_int, bitcasted_ptr);
4506 return result_loc;
4507 }
4508
4509 if (child_type->id == ZigTypeIdFloat) {
4510 LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);
4511 LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, "");
4512 return LLVMBuildBitCast(g->builder, truncated_int, get_llvm_type(g, child_type), "");
4513 }
4514
4515 return LLVMBuildTrunc(g->builder, shifted_value, get_llvm_type(g, child_type), "");
4516}
4517
4518static bool value_is_all_undef_array(CodeGen *g, ZigValue *const_val, size_t len) {
4519 switch (const_val->data.x_array.special) {
4520 case ConstArraySpecialUndef:
4521 return true;
4522 case ConstArraySpecialBuf:
4523 return false;
4524 case ConstArraySpecialNone:
4525 for (size_t i = 0; i < len; i += 1) {
4526 if (!value_is_all_undef(g, &const_val->data.x_array.data.s_none.elements[i]))
4527 return false;
4528 }
4529 return true;
4530 }
4531 zig_unreachable();
4532}
4533
4534static bool value_is_all_undef(CodeGen *g, ZigValue *const_val) {
4535 Error err;
4536 if (const_val->special == ConstValSpecialLazy &&
4537 (err = ir_resolve_lazy(g, nullptr, const_val)))
4538 codegen_report_errors_and_exit(g);
4539
4540 switch (const_val->special) {
4541 case ConstValSpecialLazy:
4542 zig_unreachable();
4543 case ConstValSpecialRuntime:
4544 return false;
4545 case ConstValSpecialUndef:
4546 return true;
4547 case ConstValSpecialStatic:
4548 if (const_val->type->id == ZigTypeIdStruct) {
4549 for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) {
4550 TypeStructField *field = const_val->type->data.structure.fields[i];
4551 if (field->is_comptime) {
4552 // Comptime fields are part of the type, may be uninitialized,
4553 // and should not be inspected.
4554 continue;
4555 }
4556 if (!value_is_all_undef(g, const_val->data.x_struct.fields[i]))
4557 return false;
4558 }
4559 return true;
4560 } else if (const_val->type->id == ZigTypeIdArray) {
4561 return value_is_all_undef_array(g, const_val, const_val->type->data.array.len);
4562 } else if (const_val->type->id == ZigTypeIdVector) {
4563 return value_is_all_undef_array(g, const_val, const_val->type->data.vector.len);
4564 } else {
4565 return false;
4566 }
4567 }
4568 zig_unreachable();
4569}
4570
4571static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default_value, LLVMValueRef request,
4572 LLVMValueRef a1, LLVMValueRef a2, LLVMValueRef a3, LLVMValueRef a4, LLVMValueRef a5)
4573{
4574 if (!target_has_valgrind_support(g->zig_target)) {
4575 return default_value;
4576 }
4577 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
4578 bool asm_has_side_effects = true;
4579 bool asm_is_alignstack = false;
4580 if (g->zig_target->arch == ZigLLVM_x86_64) {
4581 if (g->zig_target->os == OsLinux || target_os_is_darwin(g->zig_target->os) || g->zig_target->os == OsSolaris ||
4582 (g->zig_target->os == OsWindows && g->zig_target->abi != ZigLLVM_MSVC))
4583 {
4584 if (g->cur_fn->valgrind_client_request_array == nullptr) {
4585 LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder);
4586 LLVMBasicBlockRef entry_block = LLVMGetEntryBasicBlock(g->cur_fn->llvm_value);
4587 LLVMValueRef first_inst = LLVMGetFirstInstruction(entry_block);
4588 LLVMPositionBuilderBefore(g->builder, first_inst);
4589 LLVMTypeRef array_type_ref = LLVMArrayType(usize_type_ref, 6);
4590 g->cur_fn->valgrind_client_request_array = LLVMBuildAlloca(g->builder, array_type_ref, "");
4591 LLVMPositionBuilderAtEnd(g->builder, prev_block);
4592 }
4593 LLVMValueRef array_ptr = g->cur_fn->valgrind_client_request_array;
4594 LLVMValueRef array_elements[] = {request, a1, a2, a3, a4, a5};
4595 LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false);
4596 for (unsigned i = 0; i < 6; i += 1) {
4597 LLVMValueRef indexes[] = {
4598 zero,
4599 LLVMConstInt(usize_type_ref, i, false),
4600 };
4601 LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP2(g->builder,
4602 LLVMGetAllocatedType(array_ptr), array_ptr, indexes, 2, "");
4603 LLVMBuildStore(g->builder, array_elements[i], elem_ptr);
4604 }
4605
4606 Buf *asm_template = buf_create_from_str(
4607 "rolq $$3, %rdi ; rolq $$13, %rdi\n"
4608 "rolq $$61, %rdi ; rolq $$51, %rdi\n"
4609 "xchgq %rbx,%rbx\n"
4610 );
4611 Buf *asm_constraints = buf_create_from_str(
4612 "={rdx},{rax},0,~{cc},~{memory}"
4613 );
4614 unsigned input_and_output_count = 2;
4615 LLVMValueRef array_ptr_as_usize = LLVMBuildPtrToInt(g->builder, array_ptr, usize_type_ref, "");
4616 LLVMValueRef param_values[] = { array_ptr_as_usize, default_value };
4617 LLVMTypeRef param_types[] = {usize_type_ref, usize_type_ref};
4618 LLVMTypeRef function_type = LLVMFunctionType(usize_type_ref, param_types,
4619 input_and_output_count, false);
4620 LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(asm_template), buf_len(asm_template),
4621 buf_ptr(asm_constraints), buf_len(asm_constraints), asm_has_side_effects, asm_is_alignstack,
4622 LLVMInlineAsmDialectATT, false);
4623 return LLVMBuildCall2(g->builder, function_type, asm_fn, param_values, input_and_output_count, "");
4624 }
4625 }
4626 zig_unreachable();
4627}
4628
4629static void gen_valgrind_undef(CodeGen *g, LLVMValueRef dest_ptr, LLVMValueRef byte_count) {
4630 static const uint32_t VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545;
4631 ZigType *usize = g->builtin_types.entry_usize;
4632 LLVMValueRef zero = LLVMConstInt(usize->llvm_type, 0, false);
4633 LLVMValueRef req = LLVMConstInt(usize->llvm_type, VG_USERREQ__MAKE_MEM_UNDEFINED, false);
4634 LLVMValueRef ptr_as_usize = LLVMBuildPtrToInt(g->builder, dest_ptr, usize->llvm_type, "");
4635 gen_valgrind_client_request(g, zero, req, ptr_as_usize, byte_count, zero, zero, zero);
4636}
4637
4638static void gen_undef_init(CodeGen *g, ZigType *ptr_type, ZigType *value_type, LLVMValueRef ptr) {
4639 assert(type_has_bits(g, value_type));
4640
4641 uint64_t ptr_align_bytes = get_ptr_align(g, ptr_type);
4642 assert(ptr_align_bytes > 0);
4643 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, get_llvm_type(g, value_type));
4644 assert(size_bytes > 0);
4645
4646 if (ptr_type->data.pointer.host_int_bytes == 0) {
4647 // memset uninitialized memory to 0xaa
4648 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
4649 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
4650 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, "");
4651 ZigType *usize = g->builtin_types.entry_usize;
4652 LLVMValueRef byte_count = LLVMConstInt(usize->llvm_type, size_bytes, false);
4653 ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);
4654 // then tell valgrind that the memory is undefined even though we just memset it
4655 if (g->valgrind_enabled) {
4656 gen_valgrind_undef(g, dest_ptr, byte_count);
4657 }
4658 return;
4659 }
4660
4661 // This is a pointer into a packed struct, we can't use memset here.
4662 // The jury is still out on what pattern should be written here so clear the
4663 // old value and call it a day. Generating a 0xAA...AA mask for this n-bit
4664 // value is left as an exercise for the (bored) reader.
4665 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, value_type));
4666 gen_assign_raw(g, ptr, ptr_type, zero);
4667}
4668
4669static LLVMValueRef ir_render_store_ptr(CodeGen *g, Stage1Air *executable, Stage1AirInstStorePtr *instruction) {
4670 Error err;
4671
4672 ZigType *ptr_type = instruction->ptr->value->type;
4673 assert(ptr_type->id == ZigTypeIdPointer);
4674 bool ptr_type_has_bits;
4675 if ((err = type_has_bits2(g, ptr_type, &ptr_type_has_bits)))
4676 codegen_report_errors_and_exit(g);
4677 if (!ptr_type_has_bits)
4678 return nullptr;
4679 if (instruction->ptr->ref_count == 0) {
4680 // In this case, this StorePtr instruction should be elided. Something happened like this:
4681 // var t = true;
4682 // const x = if (t) Num.Two else unreachable;
4683 // The if condition is a runtime value, so the StorePtr for `x = Num.Two` got generated
4684 // (this instruction being rendered) but because of `else unreachable` the result ended
4685 // up being a comptime const value.
4686 return nullptr;
4687 }
4688
4689 bool have_init_expr = !value_is_all_undef(g, instruction->value->value);
4690 if (have_init_expr) {
4691 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
4692 LLVMValueRef value = ir_llvm_value(g, instruction->value);
4693 gen_assign_raw(g, ptr, ptr_type, value);
4694 } else if (ir_want_runtime_safety(g, &instruction->base)) {
4695 gen_undef_init(g, ptr_type, instruction->value->value->type,
4696 ir_llvm_value(g, instruction->ptr));
4697 }
4698 return nullptr;
4699}
4700
4701static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, Stage1Air *executable,
4702 Stage1AirInstVectorStoreElem *instruction)
4703{
4704 LLVMValueRef vector_ptr = ir_llvm_value(g, instruction->vector_ptr);
4705 LLVMValueRef index = ir_llvm_value(g, instruction->index);
4706 LLVMValueRef value = ir_llvm_value(g, instruction->value);
4707
4708 LLVMValueRef loaded_vector = gen_load(g, vector_ptr, instruction->vector_ptr->value->type, "");
4709 LLVMValueRef modified_vector = LLVMBuildInsertElement(g->builder, loaded_vector, value, index, "");
4710 gen_store(g, modified_vector, vector_ptr, instruction->vector_ptr->value->type);
4711 return nullptr;
4712}
4713
4714static LLVMValueRef ir_render_var_ptr(CodeGen *g, Stage1Air *executable, Stage1AirInstVarPtr *instruction) {
4715 Error err;
4716
4717 ZigType *ptr_type = instruction->base.value->type;
4718 assert(ptr_type->id == ZigTypeIdPointer);
4719 bool ptr_type_has_bits;
4720 if ((err = type_has_bits2(g, ptr_type, &ptr_type_has_bits)))
4721 codegen_report_errors_and_exit(g);
4722
4723 if (!ptr_type_has_bits) {
4724 return nullptr;
4725 }
4726
4727 // The extra bitcasts are needed in case the LLVM value is an unnamed
4728 // struct, as it happens when rendering container types with extra alignment
4729 // fields.
4730 if (instruction->base.value->special != ConstValSpecialRuntime) {
4731 return LLVMBuildBitCast(g->builder, ir_llvm_value(g, &instruction->base),
4732 get_llvm_type(g, ptr_type), "");
4733 }
4734
4735 ZigVar *var = instruction->var;
4736 assert(var->value_ref);
4737 return LLVMBuildBitCast(g->builder, var->value_ref,
4738 get_llvm_type(g, ptr_type), "");
4739}
4740
4741static LLVMValueRef ir_render_return_ptr(CodeGen *g, Stage1Air *executable,
4742 Stage1AirInstReturnPtr *instruction)
4743{
4744 if (!type_has_bits(g, instruction->base.value->type))
4745 return nullptr;
4746 ir_assert(g->cur_ret_ptr != nullptr, &instruction->base);
4747 return g->cur_ret_ptr;
4748}
4749
4750static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1AirInstElemPtr *instruction) {
4751 LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr);
4752 ZigType *array_ptr_type = instruction->array_ptr->value->type;
4753 assert(array_ptr_type->id == ZigTypeIdPointer);
4754 ZigType *array_type = array_ptr_type->data.pointer.child_type;
4755 LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index);
4756 assert(subscript_value);
4757
4758 if (!type_has_bits(g, array_type))
4759 return nullptr;
4760
4761 bool safety_check_on = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on;
4762
4763 if (array_type->id == ZigTypeIdArray ||
4764 (array_type->id == ZigTypeIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
4765 {
4766 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
4767 if (array_type->id == ZigTypeIdPointer) {
4768 assert(array_type->data.pointer.child_type->id == ZigTypeIdArray);
4769 array_type = array_type->data.pointer.child_type;
4770 }
4771
4772 assert(array_type->data.array.len != 0 || array_type->data.array.sentinel != nullptr);
4773
4774 if (safety_check_on) {
4775 uint64_t extra_len_from_sentinel = (array_type->data.array.sentinel != nullptr) ? 1 : 0;
4776 uint64_t full_len = array_type->data.array.len + extra_len_from_sentinel;
4777 LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, full_len, false);
4778 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
4779 }
4780 if (array_ptr_type->data.pointer.host_int_bytes != 0) {
4781 return array_ptr_ptr;
4782 }
4783 ZigType *child_type = array_type->data.array.child_type;
4784 if (child_type->id == ZigTypeIdStruct &&
4785 child_type->data.structure.layout == ContainerLayoutPacked)
4786 {
4787 ZigType *ptr_type = instruction->base.value->type;
4788 size_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;
4789 if (host_int_bytes != 0) {
4790 uint32_t size_in_bits = type_size_bits(g, ptr_type->data.pointer.child_type);
4791 LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0);
4792 LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, "");
4793 assert(size_in_bits % 8 == 0);
4794 LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
4795 size_in_bits / 8, false);
4796 LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, "");
4797 LLVMValueRef indices[] = { byte_offset };
4798 LLVMValueRef elem_byte_ptr = LLVMBuildInBoundsGEP2(g->builder, LLVMInt8Type(),
4799 u8_array_ptr, indices, 1, "");
4800 return LLVMBuildBitCast(g->builder, elem_byte_ptr, LLVMPointerType(get_llvm_type(g, child_type), 0), "");
4801 }
4802 }
4803 LLVMValueRef indices[] = {
4804 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
4805 subscript_value
4806 };
4807 return LLVMBuildInBoundsGEP2(g->builder, get_llvm_type(g, array_type), array_ptr,
4808 indices, 2, "");
4809 } else if (array_type->id == ZigTypeIdPointer) {
4810 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
4811 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
4812 LLVMValueRef indices[] = { subscript_value };
4813 LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.pointer.child_type);
4814 return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, array_ptr, indices, 1, "");
4815 } else if (array_type->id == ZigTypeIdStruct) {
4816 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
4817 assert(array_type->data.structure.special == StructSpecialSlice);
4818
4819 ZigType *ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
4820 if (!type_has_bits(g, ptr_type)) {
4821 if (safety_check_on) {
4822 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMIntegerTypeKind);
4823 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, array_ptr);
4824 }
4825 return nullptr;
4826 }
4827
4828 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
4829
4830 if (safety_check_on) {
4831 size_t len_index = array_type->data.structure.fields[slice_len_index]->gen_index;
4832 assert(len_index != SIZE_MAX);
4833 LLVMValueRef len_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type),
4834 array_ptr, (unsigned)len_index, "");
4835 LLVMValueRef len = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_ptr), len_ptr,
4836 0, false, "");
4837 LLVMIntPredicate upper_op = (ptr_type->data.pointer.sentinel != nullptr) ? LLVMIntULE : LLVMIntULT;
4838 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, upper_op, len);
4839 }
4840
4841 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index;
4842 assert(ptr_index != SIZE_MAX);
4843 LLVMValueRef ptr_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type),
4844 array_ptr, (unsigned)ptr_index, "");
4845 LLVMValueRef ptr = gen_load_untyped(g,
4846 LLVMPointerTypeInContext(LLVMGetGlobalContext(), 0), ptr_ptr, 0, false, "");
4847 LLVMTypeRef elem_llvm_ty = get_llvm_type(g, ptr_type->data.pointer.child_type);
4848 return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, ptr, &subscript_value, 1, "");
4849 } else if (array_type->id == ZigTypeIdVector) {
4850 return array_ptr_ptr;
4851 } else {
4852 zig_unreachable();
4853 }
4854}
4855
4856static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMTypeRef new_stack_llvm_ty,
4857 LLVMValueRef new_stack)
4858{
4859 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, new_stack_llvm_ty, new_stack, (unsigned)slice_ptr_index, "");
4860 LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, new_stack_llvm_ty, new_stack, (unsigned)slice_len_index, "");
4861
4862 LLVMValueRef ptr_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_field_ptr),
4863 ptr_field_ptr, 0, false, "");
4864 LLVMValueRef len_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_field_ptr),
4865 len_field_ptr, 0, false, "");
4866
4867 LLVMValueRef ptr_addr = LLVMBuildPtrToInt(g->builder, ptr_value, LLVMTypeOf(len_value), "");
4868 LLVMValueRef end_addr = LLVMBuildNUWAdd(g->builder, ptr_addr, len_value, "");
4869 const unsigned alignment_factor = ZigLLVMDataLayoutGetStackAlignment(g->target_data_ref);
4870 LLVMValueRef align_amt = LLVMConstInt(LLVMTypeOf(end_addr), alignment_factor, false);
4871 LLVMValueRef align_adj = LLVMBuildURem(g->builder, end_addr, align_amt, "");
4872 return LLVMBuildNUWSub(g->builder, end_addr, align_adj, "");
4873}
4874
4875static void gen_set_stack_pointer(CodeGen *g, LLVMValueRef aligned_end_addr) {
4876 LLVMValueRef write_register_fn_val = get_write_register_fn_val(g);
4877
4878 if (g->sp_md_node == nullptr) {
4879 Buf *sp_reg_name = buf_create_from_str(arch_stack_pointer_register_name(g->zig_target->arch));
4880 LLVMValueRef str_node = LLVMMDString(buf_ptr(sp_reg_name), buf_len(sp_reg_name) + 1);
4881 g->sp_md_node = LLVMMDNode(&str_node, 1);
4882 }
4883
4884 LLVMValueRef params[] = {
4885 g->sp_md_node,
4886 aligned_end_addr,
4887 };
4888
4889 LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(write_register_fn_val), write_register_fn_val, params, 2, "");
4890}
4891
4892static void render_async_spills(CodeGen *g) {
4893 ZigType *fn_type = g->cur_fn->type_entry;
4894 ZigType *import = get_scope_import(&g->cur_fn->fndef_scope->base);
4895
4896 CalcLLVMFieldIndex arg_calc = {0};
4897 frame_index_arg_calc(g, &arg_calc, fn_type->data.fn.fn_type_id.return_type);
4898 for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) {
4899 ZigVar *var = g->cur_fn->variable_list.at(var_i);
4900
4901 if (!type_has_bits(g, var->var_type)) {
4902 continue;
4903 }
4904 if (ir_get_var_is_comptime(var))
4905 continue;
4906 switch (type_requires_comptime(g, var->var_type)) {
4907 case ReqCompTimeInvalid:
4908 zig_unreachable();
4909 case ReqCompTimeYes:
4910 continue;
4911 case ReqCompTimeNo:
4912 break;
4913 }
4914 if (var->src_arg_index == SIZE_MAX) {
4915 continue;
4916 }
4917
4918 calc_llvm_field_index_add(g, &arg_calc, var->var_type);
4919 var->value_ref = LLVMBuildStructGEP2(g->builder,
4920 get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)),
4921 g->cur_frame_ptr, arg_calc.field_index - 1, var->name);
4922 if (var->decl_node) {
4923 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
4924 var->name, import->data.structure.root_struct->di_file,
4925 node_line_onebased(var->decl_node),
4926 get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0);
4927 gen_var_debug_decl(g, var);
4928 }
4929 }
4930
4931 ZigType *frame_type = g->cur_fn->frame_type->data.frame.locals_struct;
4932
4933 for (size_t alloca_i = 0; alloca_i < g->cur_fn->alloca_gen_list.length; alloca_i += 1) {
4934 Stage1AirInstAlloca *instruction = g->cur_fn->alloca_gen_list.at(alloca_i);
4935 if (instruction->field_index == SIZE_MAX)
4936 continue;
4937
4938 size_t gen_index = frame_type->data.structure.fields[instruction->field_index]->gen_index;
4939 instruction->base.llvm_value = LLVMBuildStructGEP2(g->builder,
4940 get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)),
4941 g->cur_frame_ptr, gen_index,
4942 instruction->name_hint);
4943 }
4944}
4945
4946static void render_async_var_decls(CodeGen *g, Scope *scope) {
4947 for (;;) {
4948 switch (scope->id) {
4949 case ScopeIdCImport:
4950 zig_unreachable();
4951 case ScopeIdFnDef:
4952 return;
4953 case ScopeIdVarDecl: {
4954 ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var;
4955 if (var->did_the_decl_codegen) {
4956 render_decl_var(g, var);
4957 }
4958 }
4959 ZIG_FALLTHROUGH;
4960
4961 case ScopeIdDecls:
4962 case ScopeIdBlock:
4963 case ScopeIdDefer:
4964 case ScopeIdDeferExpr:
4965 case ScopeIdLoop:
4966 case ScopeIdSuspend:
4967 case ScopeIdCompTime:
4968 case ScopeIdNoSuspend:
4969 case ScopeIdRuntime:
4970 case ScopeIdTypeOf:
4971 case ScopeIdExpr:
4972 scope = scope->parent;
4973 continue;
4974 }
4975 }
4976}
4977
4978static LLVMValueRef gen_frame_size(CodeGen *g, LLVMValueRef fn_val) {
4979 assert(g->need_frame_size_prefix_data);
4980 LLVMTypeRef usize_llvm_type = g->builtin_types.entry_usize->llvm_type;
4981 LLVMTypeRef ptr_usize_llvm_type = LLVMPointerType(usize_llvm_type, 0);
4982 LLVMValueRef casted_fn_val = LLVMBuildBitCast(g->builder, fn_val, ptr_usize_llvm_type, "");
4983 LLVMValueRef negative_one = LLVMConstInt(LLVMInt32Type(), -1, true);
4984 LLVMValueRef prefix_ptr = LLVMBuildInBoundsGEP2(g->builder, usize_llvm_type, casted_fn_val, &negative_one, 1, "");
4985 LLVMValueRef load_inst = LLVMBuildLoad2(g->builder, usize_llvm_type, prefix_ptr, "");
4986
4987 // Some architectures (e.g SPARCv9) has different alignment requirements between a
4988 // function/usize pointer and also require all loads to be aligned.
4989 // On those architectures, not explicitly setting the alignment will lead into @frameSize
4990 // generating usize-aligned load instruction that could crash if the function pointer
4991 // happens to be not usize-aligned.
4992 LLVMSetAlignment(load_inst, 1);
4993 return load_inst;
4994}
4995
4996static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMValueRef addrs_field_ptr) {
4997 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
4998 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
4999 LLVMTypeRef stack_trace_llvm_ty = get_llvm_type(g, get_stack_trace_type(g));
5000
5001 LLVMValueRef index_ptr = LLVMBuildStructGEP2(g->builder, stack_trace_llvm_ty, trace_field_ptr, 0, "");
5002 LLVMBuildStore(g->builder, zero, index_ptr);
5003
5004 LLVMValueRef addrs_slice_ptr = LLVMBuildStructGEP2(g->builder, stack_trace_llvm_ty, trace_field_ptr, 1, "");
5005 LLVMValueRef addrs_ptr_ptr = LLVMBuildStructGEP2(g->builder,
5006 ZigLLVMGetGEPResultElementType(addrs_slice_ptr),
5007 addrs_slice_ptr, slice_ptr_index, "");
5008 LLVMValueRef indices[] = { LLVMConstNull(usize_type_ref), LLVMConstNull(usize_type_ref) };
5009 LLVMValueRef trace_field_addrs_as_ptr = LLVMBuildInBoundsGEP2(g->builder,
5010 ZigLLVMGetGEPResultElementType(addrs_field_ptr), addrs_field_ptr, indices, 2, "");
5011 LLVMBuildStore(g->builder, trace_field_addrs_as_ptr, addrs_ptr_ptr);
5012
5013 LLVMValueRef addrs_len_ptr = LLVMBuildStructGEP2(g->builder,
5014 ZigLLVMGetGEPResultElementType(addrs_slice_ptr),
5015 addrs_slice_ptr, slice_len_index, "");
5016 LLVMBuildStore(g->builder, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), addrs_len_ptr);
5017}
5018
5019static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirInstCall *instruction) {
5020 Error err;
5021
5022 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
5023
5024 LLVMValueRef fn_val;
5025 LLVMTypeRef fn_llvm_ty;
5026 ZigType *fn_type;
5027 bool callee_is_async;
5028 if (instruction->fn_entry) {
5029 fn_val = fn_llvm_value(g, instruction->fn_entry);
5030 fn_type = instruction->fn_entry->type_entry;
5031 callee_is_async = fn_is_async(instruction->fn_entry);
5032 fn_llvm_ty = LLVMGlobalGetValueType(fn_val);
5033 } else {
5034 assert(instruction->fn_ref);
5035 fn_val = ir_llvm_value(g, instruction->fn_ref);
5036 fn_type = instruction->fn_ref->value->type;
5037 callee_is_async = fn_type->data.fn.fn_type_id.cc == CallingConventionAsync;
5038 fn_llvm_ty = fn_type->data.fn.raw_type_ref;
5039 }
5040
5041 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
5042
5043 ZigType *src_return_type = fn_type_id->return_type;
5044 bool ret_has_bits = type_has_bits(g, src_return_type);
5045
5046 CallingConvention cc = fn_type->data.fn.fn_type_id.cc;
5047
5048 bool first_arg_ret = ret_has_bits && want_first_arg_sret(g, fn_type_id);
5049 bool prefix_arg_err_ret_stack = codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type);
5050 bool is_var_args = fn_type_id->is_var_args;
5051 ZigList<LLVMValueRef> gen_param_values = {};
5052 ZigList<ZigType *> gen_param_types = {};
5053 LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr;
5054 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
5055 bool need_frame_ptr_ptr_spill = false;
5056 ZigType *anyframe_type = nullptr;
5057 LLVMValueRef frame_result_loc_uncasted = nullptr;
5058 LLVMValueRef frame_result_loc;
5059 LLVMTypeRef frame_struct_llvm_ty;
5060 LLVMValueRef awaiter_init_val;
5061 LLVMValueRef ret_ptr;
5062 if (callee_is_async) {
5063 if (instruction->new_stack == nullptr) {
5064 if (instruction->modifier == CallModifierAsync) {
5065 frame_result_loc = result_loc;
5066 if (result_loc != nullptr) {
5067 ir_assert(instruction->result_loc->value->type->id == ZigTypeIdPointer, &instruction->base);
5068 frame_struct_llvm_ty = get_llvm_type(g, instruction->result_loc->value->type->data.pointer.child_type);
5069 } else {
5070 frame_struct_llvm_ty = nullptr;
5071 }
5072 } else {
5073 ir_assert(instruction->frame_result_loc != nullptr, &instruction->base);
5074 frame_result_loc_uncasted = ir_llvm_value(g, instruction->frame_result_loc);
5075 ir_assert(instruction->fn_entry != nullptr, &instruction->base);
5076 frame_struct_llvm_ty = get_llvm_type(g, instruction->fn_entry->frame_type);
5077 frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted,
5078 LLVMPointerType(frame_struct_llvm_ty, 0), "");
5079 }
5080 } else {
5081 if (instruction->new_stack->value->type->id == ZigTypeIdPointer &&
5082 instruction->new_stack->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame)
5083 {
5084 frame_result_loc = ir_llvm_value(g, instruction->new_stack);
5085 frame_struct_llvm_ty = get_llvm_type(g, instruction->new_stack->value->type->data.pointer.child_type);
5086 } else {
5087 LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack);
5088 LLVMTypeRef frame_slice_llvm_ty = get_llvm_type(g, instruction->new_stack->value->type);
5089 if (ir_want_runtime_safety(g, &instruction->base)) {
5090 LLVMValueRef given_len_ptr = LLVMBuildStructGEP2(g->builder,
5091 frame_slice_llvm_ty, frame_slice_ptr, slice_len_index, "");
5092 LLVMValueRef given_frame_len = LLVMBuildLoad2(g->builder, usize_type_ref, given_len_ptr, "");
5093 LLVMValueRef actual_frame_len = gen_frame_size(g, fn_val);
5094
5095 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "FrameSizeCheckFail");
5096 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "FrameSizeCheckOk");
5097
5098 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntUGE, given_frame_len, actual_frame_len, "");
5099 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
5100
5101 LLVMPositionBuilderAtEnd(g->builder, fail_block);
5102 gen_safety_crash(g, PanicMsgIdFrameTooSmall);
5103
5104 LLVMPositionBuilderAtEnd(g->builder, ok_block);
5105 }
5106 need_frame_ptr_ptr_spill = true;
5107 LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_slice_llvm_ty,
5108 frame_slice_ptr, slice_ptr_index, "");
5109 LLVMValueRef frame_ptr = LLVMBuildLoad2(g->builder,
5110 ZigLLVMGetGEPResultElementType(frame_ptr_ptr), frame_ptr_ptr, "");
5111 if (instruction->fn_entry == nullptr) {
5112 anyframe_type = get_any_frame_type(g, src_return_type);
5113 frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, get_llvm_type(g, anyframe_type), "");
5114 frame_struct_llvm_ty = anyframe_type->data.any_frame.struct_llvm_ty;
5115 } else {
5116 ZigType *frame_type = get_fn_frame_type(g, instruction->fn_entry);
5117 if ((err = type_resolve(g, frame_type, ResolveStatusLLVMFull)))
5118 codegen_report_errors_and_exit(g);
5119 ZigType *ptr_frame_type = get_pointer_to_type(g, frame_type, false);
5120 frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr,
5121 get_llvm_type(g, ptr_frame_type), "");
5122 frame_struct_llvm_ty = get_llvm_type(g, frame_type);
5123 }
5124 }
5125 }
5126 if (instruction->modifier == CallModifierAsync) {
5127 if (instruction->new_stack == nullptr) {
5128 awaiter_init_val = zero;
5129
5130 if (ret_has_bits) {
5131 // Use the result location which is inside the frame if this is an async call.
5132 ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty,
5133 frame_result_loc, frame_ret_start + 2, "");
5134 }
5135 } else {
5136 awaiter_init_val = zero;
5137
5138 if (ret_has_bits) {
5139 if (result_loc != nullptr) {
5140 // Use the result location provided to the @asyncCall builtin
5141 ret_ptr = result_loc;
5142 } else {
5143 // no result location provided to @asyncCall - use the one inside the frame.
5144 ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty,
5145 frame_result_loc, frame_ret_start + 2, "");
5146 }
5147 }
5148 }
5149
5150 // even if prefix_arg_err_ret_stack is true, let the async function do its own
5151 // initialization.
5152 } else {
5153 if (instruction->modifier == CallModifierNoSuspend && !fn_is_async(g->cur_fn)) {
5154 // Async function called as a normal function, and calling function is not async.
5155 // This is allowed because it was called with `nosuspend` which asserts that it will
5156 // never suspend.
5157 awaiter_init_val = zero;
5158 } else {
5159 // async function called as a normal function
5160 awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); // caller's own frame pointer
5161 }
5162 if (ret_has_bits) {
5163 if (result_loc == nullptr) {
5164 // return type is a scalar, but we still need a pointer to it. Use the async fn frame.
5165 ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start + 2, "");
5166 } else {
5167 // Use the call instruction's result location.
5168 ret_ptr = result_loc;
5169 }
5170
5171 // Store a zero in the awaiter's result ptr to indicate we do not need a copy made.
5172 LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start + 1, "");
5173 LLVMValueRef zero_ptr = LLVMConstNull(ZigLLVMGetGEPResultElementType(awaiter_ret_ptr));
5174 LLVMBuildStore(g->builder, zero_ptr, awaiter_ret_ptr);
5175 }
5176
5177 if (prefix_arg_err_ret_stack) {
5178 LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc,
5179 frame_index_trace_arg(g, src_return_type) + 1, "");
5180 bool is_llvm_alloca;
5181 LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope,
5182 &is_llvm_alloca);
5183 LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr);
5184 }
5185 }
5186
5187 assert(frame_result_loc != nullptr);
5188
5189 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_fn_ptr_index, "");
5190 LLVMValueRef bitcasted_fn_val = LLVMBuildBitCast(g->builder, fn_val,
5191 LLVMPointerTypeInContext(LLVMGetGlobalContext(), 0), "");
5192 LLVMBuildStore(g->builder, bitcasted_fn_val, fn_ptr_ptr);
5193
5194 LLVMValueRef resume_index_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_resume_index, "");
5195 LLVMBuildStore(g->builder, zero, resume_index_ptr);
5196
5197 LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_awaiter_index, "");
5198 LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr);
5199
5200 if (ret_has_bits) {
5201 LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start, "");
5202 LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr);
5203 }
5204 } else if (instruction->modifier == CallModifierAsync) {
5205 // Async call of blocking function
5206 if (instruction->new_stack != nullptr) {
5207 zig_panic("TODO @asyncCall of non-async function");
5208 }
5209 frame_result_loc = result_loc;
5210 if (result_loc != nullptr) {
5211 ir_assert(instruction->result_loc->value->type->id == ZigTypeIdPointer, &instruction->base);
5212 frame_struct_llvm_ty = get_llvm_type(g, instruction->result_loc->value->type->data.pointer.child_type);
5213 } else {
5214 frame_struct_llvm_ty = nullptr;
5215 }
5216 awaiter_init_val = LLVMConstAllOnes(usize_type_ref);
5217
5218 LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_awaiter_index, "");
5219 LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr);
5220
5221 if (ret_has_bits) {
5222 ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start + 2, "");
5223 LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start, "");
5224 LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr);
5225
5226 if (first_arg_ret) {
5227 gen_param_values.append(ret_ptr);
5228 }
5229 if (prefix_arg_err_ret_stack) {
5230 // Set up the callee stack trace pointer pointing into the frame.
5231 // Then we have to wire up the StackTrace pointers.
5232 // Await is responsible for merging error return traces.
5233 uint32_t trace_field_index_start = frame_index_trace_arg(g, src_return_type);
5234 LLVMValueRef callee_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc,
5235 trace_field_index_start, "");
5236 LLVMValueRef trace_field_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc,
5237 trace_field_index_start + 2, "");
5238 LLVMValueRef addrs_field_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc,
5239 trace_field_index_start + 3, "");
5240
5241 LLVMBuildStore(g->builder, trace_field_ptr, callee_trace_ptr_ptr);
5242
5243 gen_init_stack_trace(g, trace_field_ptr, addrs_field_ptr);
5244
5245 bool is_llvm_alloca;
5246 gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca));
5247 }
5248 }
5249 } else {
5250 if (first_arg_ret) {
5251 gen_param_values.append(result_loc);
5252 }
5253 if (prefix_arg_err_ret_stack) {
5254 bool is_llvm_alloca;
5255 gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca));
5256 }
5257 }
5258 FnWalk fn_walk = {};
5259 fn_walk.id = FnWalkIdCall;
5260 fn_walk.data.call.inst = instruction;
5261 fn_walk.data.call.is_var_args = is_var_args;
5262 fn_walk.data.call.gen_param_values = &gen_param_values;
5263 fn_walk.data.call.gen_param_types = &gen_param_types;
5264 walk_function_params(g, fn_type, &fn_walk);
5265
5266 ZigLLVM_CallAttr call_attr;
5267 switch (instruction->modifier) {
5268 case CallModifierBuiltin:
5269 case CallModifierCompileTime:
5270 zig_unreachable();
5271 case CallModifierNone:
5272 case CallModifierNoSuspend:
5273 case CallModifierAsync:
5274 call_attr = ZigLLVM_CallAttrAuto;
5275 break;
5276 case CallModifierNeverTail:
5277 call_attr = ZigLLVM_CallAttrNeverTail;
5278 break;
5279 case CallModifierNeverInline:
5280 call_attr = ZigLLVM_CallAttrNeverInline;
5281 break;
5282 case CallModifierAlwaysTail:
5283 call_attr = ZigLLVM_CallAttrAlwaysTail;
5284 break;
5285 case CallModifierAlwaysInline:
5286 ir_assert(instruction->fn_entry != nullptr, &instruction->base);
5287 call_attr = ZigLLVM_CallAttrAlwaysInline;
5288 break;
5289 }
5290
5291 ZigLLVM_CallingConv llvm_cc = get_llvm_cc(g, cc);
5292 LLVMValueRef result;
5293
5294 if (callee_is_async) {
5295 CalcLLVMFieldIndex arg_calc_start = {0};
5296 frame_index_arg_calc(g, &arg_calc_start, fn_type->data.fn.fn_type_id.return_type);
5297
5298 LLVMValueRef casted_frame;
5299 LLVMTypeRef casted_frame_llvm_ty;
5300 if (instruction->new_stack != nullptr && instruction->fn_entry == nullptr) {
5301 // We need the frame type to be a pointer to a struct that includes the args
5302
5303 // Count ahead to determine how many llvm struct fields we need.
5304 CalcLLVMFieldIndex arg_calc = arg_calc_start;
5305 for (size_t i = 0; i < gen_param_types.length; i += 1) {
5306 calc_llvm_field_index_add(g, &arg_calc, gen_param_types.at(i));
5307 }
5308 size_t field_count = arg_calc.field_index;
5309
5310 LLVMTypeRef *field_types = heap::c_allocator.allocate_nonzero<LLVMTypeRef>(field_count);
5311 LLVMGetStructElementTypes(frame_struct_llvm_ty, field_types);
5312 assert(LLVMCountStructElementTypes(frame_struct_llvm_ty) == arg_calc_start.field_index);
5313
5314 arg_calc = arg_calc_start;
5315 for (size_t arg_i = 0; arg_i < gen_param_values.length; arg_i += 1) {
5316 CalcLLVMFieldIndex prev = arg_calc;
5317 // Use the declared argument type and not the value one to be
5318 // consistent with the assignment operation below.
5319 calc_llvm_field_index_add(g, &arg_calc, gen_param_types.at(arg_i));
5320 field_types[arg_calc.field_index - 1] = get_llvm_type(g, gen_param_types.at(arg_i));
5321 if (arg_calc.field_index - prev.field_index > 1) {
5322 // Padding field
5323 uint32_t pad_bytes = arg_calc.offset - prev.offset - gen_param_types.at(arg_i)->abi_size;
5324 LLVMTypeRef pad_llvm_type = LLVMArrayType(LLVMInt8Type(), pad_bytes);
5325 field_types[arg_calc.field_index - 2] = pad_llvm_type;
5326 }
5327 }
5328 LLVMTypeRef frame_with_args_type = LLVMStructType(field_types, field_count, false);
5329 heap::c_allocator.deallocate(field_types, field_count);
5330 LLVMTypeRef ptr_frame_with_args_type = LLVMPointerType(frame_with_args_type, 0);
5331
5332 casted_frame = LLVMBuildBitCast(g->builder, frame_result_loc, ptr_frame_with_args_type, "");
5333 casted_frame_llvm_ty = frame_with_args_type;
5334 } else {
5335 casted_frame = frame_result_loc;
5336 casted_frame_llvm_ty = frame_struct_llvm_ty;
5337 }
5338
5339 CalcLLVMFieldIndex arg_calc = arg_calc_start;
5340 for (size_t arg_i = 0; arg_i < gen_param_values.length; arg_i += 1) {
5341 calc_llvm_field_index_add(g, &arg_calc, gen_param_types.at(arg_i));
5342 LLVMValueRef arg_ptr = LLVMBuildStructGEP2(g->builder, casted_frame_llvm_ty, casted_frame, arg_calc.field_index - 1, "");
5343 gen_assign_raw(g, arg_ptr, get_pointer_to_type(g, gen_param_types.at(arg_i), true),
5344 gen_param_values.at(arg_i));
5345 }
5346 gen_param_types.deinit();
5347
5348 if (instruction->modifier == CallModifierAsync) {
5349 gen_resume(g, fn_llvm_ty, fn_val, frame_result_loc, ResumeIdCall);
5350 if (instruction->new_stack != nullptr) {
5351 return LLVMBuildBitCast(g->builder, frame_result_loc,
5352 get_llvm_type(g, instruction->base.value->type), "");
5353 }
5354 return nullptr;
5355 } else if (instruction->modifier == CallModifierNoSuspend && !fn_is_async(g->cur_fn)) {
5356 gen_resume(g, fn_llvm_ty, fn_val, frame_result_loc, ResumeIdCall);
5357
5358 if (ir_want_runtime_safety(g, &instruction->base)) {
5359 LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty,
5360 frame_result_loc, frame_awaiter_index, "");
5361 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);
5362 LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr,
5363 all_ones, LLVMAtomicOrderingRelease);
5364 LLVMValueRef ok_val = LLVMBuildICmp(g->builder, LLVMIntEQ, prev_val, all_ones, "");
5365
5366 LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "NoSuspendPanic");
5367 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "NoSuspendOk");
5368 LLVMBuildCondBr(g->builder, ok_val, ok_block, bad_block);
5369
5370 // The async function suspended, but this nosuspend call asserted it wouldn't.
5371 LLVMPositionBuilderAtEnd(g->builder, bad_block);
5372 gen_safety_crash(g, PanicMsgIdBadNoSuspendCall);
5373
5374 LLVMPositionBuilderAtEnd(g->builder, ok_block);
5375 }
5376
5377 ZigType *result_type = instruction->base.value->type;
5378 ZigType *ptr_result_type = get_pointer_to_type(g, result_type, true);
5379 return gen_await_early_return(g, &instruction->base,
5380 frame_struct_llvm_ty, frame_result_loc,
5381 result_type, ptr_result_type, result_loc, true);
5382 } else {
5383 ZigType *ptr_result_type = get_pointer_to_type(g, src_return_type, true);
5384
5385 LLVMBasicBlockRef call_bb = gen_suspend_begin(g, "CallResume");
5386
5387 LLVMValueRef call_inst = gen_resume(g, fn_llvm_ty, fn_val, frame_result_loc, ResumeIdCall);
5388 set_tail_call_if_appropriate(g, call_inst);
5389 LLVMBuildRetVoid(g->builder);
5390
5391 LLVMPositionBuilderAtEnd(g->builder, call_bb);
5392 gen_assert_resume_id(g, &instruction->base, ResumeIdReturn, PanicMsgIdResumedAnAwaitingFn, nullptr);
5393 render_async_var_decls(g, instruction->base.scope);
5394
5395 if (!type_has_bits(g, src_return_type))
5396 return nullptr;
5397
5398 if (result_loc != nullptr) {
5399 if (instruction->result_loc->id == Stage1AirInstIdReturnPtr) {
5400 instruction->base.spill = nullptr;
5401 return g->cur_ret_ptr;
5402 } else {
5403 return get_handle_value(g, result_loc, src_return_type, ptr_result_type);
5404 }
5405 }
5406
5407 if (need_frame_ptr_ptr_spill) {
5408 LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack);
5409 LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP2(g->builder,
5410 get_llvm_type(g, instruction->new_stack->value->type),
5411 frame_slice_ptr, slice_ptr_index, "");
5412 frame_result_loc_uncasted = LLVMBuildLoad2(g->builder,
5413 ZigLLVMGetGEPResultElementType(frame_ptr_ptr), frame_ptr_ptr, "");
5414 }
5415 if (frame_result_loc_uncasted != nullptr) {
5416 if (instruction->fn_entry != nullptr) {
5417 frame_struct_llvm_ty = get_llvm_type(g, instruction->fn_entry->frame_type);
5418 frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted,
5419 LLVMPointerType(frame_struct_llvm_ty, 0), "");
5420 } else {
5421 frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted,
5422 get_llvm_type(g, anyframe_type), "");
5423 frame_struct_llvm_ty = anyframe_type->data.any_frame.struct_llvm_ty;
5424 }
5425 }
5426
5427 LLVMValueRef result_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty,
5428 frame_result_loc, frame_ret_start + 2, "");
5429 return LLVMBuildLoad2(g->builder, get_llvm_type(g, src_return_type), result_ptr, "");
5430 }
5431 } else {
5432 gen_param_types.deinit();
5433 }
5434
5435 if (instruction->new_stack == nullptr || instruction->is_async_call_builtin) {
5436 result = ZigLLVMBuildCall(g->builder, fn_llvm_ty, fn_val,
5437 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, "");
5438 } else if (instruction->modifier == CallModifierAsync) {
5439 zig_panic("TODO @asyncCall of non-async function");
5440 } else {
5441 LLVMValueRef new_stack_addr = get_new_stack_addr(g,
5442 get_llvm_type(g, instruction->new_stack->value->type),
5443 ir_llvm_value(g, instruction->new_stack));
5444 LLVMValueRef old_stack_ref;
5445 if (src_return_type->id != ZigTypeIdUnreachable) {
5446 LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g);
5447 old_stack_ref = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(stacksave_fn_val), stacksave_fn_val, nullptr, 0, "");
5448 }
5449 gen_set_stack_pointer(g, new_stack_addr);
5450 result = ZigLLVMBuildCall(g->builder, fn_llvm_ty, fn_val,
5451 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, "");
5452 if (src_return_type->id != ZigTypeIdUnreachable) {
5453 LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g);
5454 LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(stackrestore_fn_val), stackrestore_fn_val, &old_stack_ref, 1, "");
5455 }
5456 }
5457
5458 if (src_return_type->id == ZigTypeIdUnreachable) {
5459 return LLVMBuildUnreachable(g->builder);
5460 } else if (!ret_has_bits) {
5461 return nullptr;
5462 } else if (first_arg_ret) {
5463 ZigLLVMSetCallSret(result, get_llvm_type(g, src_return_type));
5464 return result_loc;
5465 } else if (fn_returns_c_abi_small_struct(fn_type_id)) {
5466 LLVMTypeRef abi_type = get_llvm_c_abi_type(g, src_return_type);
5467 LLVMTypeRef abi_type_ptr = LLVMPointerType(abi_type, 0);
5468 LLVMValueRef bitcast = LLVMBuildBitCast(g->builder, result_loc, abi_type_ptr, "");
5469 LLVMBuildStore(g->builder, result, bitcast);
5470 return result_loc;
5471 } else if (handle_is_ptr(g, src_return_type)) {
5472 LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);
5473 LLVMSetAlignment(store_instr, get_ptr_align(g, instruction->result_loc->value->type));
5474 return result_loc;
5475 } else if (!callee_is_async && instruction->modifier == CallModifierAsync) {
5476 LLVMBuildStore(g->builder, result, ret_ptr);
5477 return result_loc;
5478 } else {
5479 return result;
5480 }
5481}
5482
5483static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, Stage1Air *executable,
5484 Stage1AirInstStructFieldPtr *instruction)
5485{
5486 Error err;
5487
5488 if (instruction->base.value->special != ConstValSpecialRuntime)
5489 return nullptr;
5490
5491 LLVMValueRef struct_ptr = ir_llvm_value(g, instruction->struct_ptr);
5492 // not necessarily a pointer. could be ZigTypeIdStruct
5493 ZigType *struct_ptr_type = instruction->struct_ptr->value->type;
5494 TypeStructField *field = instruction->field;
5495
5496 if (!type_has_bits(g, field->type_entry))
5497 return nullptr;
5498
5499 if (struct_ptr_type->id == ZigTypeIdPointer &&
5500 struct_ptr_type->data.pointer.host_int_bytes != 0)
5501 {
5502 return struct_ptr;
5503 }
5504
5505 ZigType *struct_type;
5506 if (struct_ptr_type->id == ZigTypeIdPointer) {
5507 if (struct_ptr_type->data.pointer.inferred_struct_field != nullptr) {
5508 struct_type = struct_ptr_type->data.pointer.inferred_struct_field->inferred_struct_type;
5509 } else {
5510 struct_type = struct_ptr_type->data.pointer.child_type;
5511 }
5512 } else {
5513 struct_type = struct_ptr_type;
5514 }
5515
5516 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))
5517 codegen_report_errors_and_exit(g);
5518
5519 ir_assert(field->gen_index != SIZE_MAX, &instruction->base);
5520 LLVMValueRef field_ptr_val = LLVMBuildStructGEP2(g->builder,
5521 get_llvm_type(g, struct_type), struct_ptr, (unsigned)field->gen_index, "");
5522 ZigType *res_type = instruction->base.value->type;
5523 ir_assert(res_type->id == ZigTypeIdPointer, &instruction->base);
5524 if (res_type->data.pointer.host_int_bytes != 0) {
5525 // We generate packed structs with get_llvm_type_of_n_bytes, which is
5526 // u8 for 1 byte or [n]u8 for multiple bytes. But the pointer to the type
5527 // is supposed to be a pointer to the integer. So we bitcast it here.
5528 LLVMTypeRef int_elem_type = LLVMIntType(8*res_type->data.pointer.host_int_bytes);
5529 LLVMTypeRef integer_ptr_type = LLVMPointerType(int_elem_type, 0);
5530 return LLVMBuildBitCast(g->builder, field_ptr_val, integer_ptr_type, "");
5531 }
5532 return field_ptr_val;
5533}
5534
5535static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, Stage1Air *executable,
5536 Stage1AirInstUnionFieldPtr *instruction)
5537{
5538 if (instruction->base.value->special != ConstValSpecialRuntime)
5539 return nullptr;
5540
5541 ZigType *union_ptr_type = instruction->union_ptr->value->type;
5542 assert(union_ptr_type->id == ZigTypeIdPointer);
5543 ZigType *union_type = union_ptr_type->data.pointer.child_type;
5544 assert(union_type->id == ZigTypeIdUnion);
5545
5546 TypeUnionField *field = instruction->field;
5547
5548 if (!type_has_bits(g, field->type_entry)) {
5549 ZigType *tag_type = union_type->data.unionation.tag_type;
5550 if (!instruction->initializing || tag_type == nullptr || !type_has_bits(g, tag_type))
5551 return nullptr;
5552
5553 // The field has no bits but we still have to change the discriminant
5554 // value here
5555 LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr);
5556
5557 LLVMTypeRef tag_type_ref = get_llvm_type(g, tag_type);
5558 LLVMValueRef tag_field_ptr = nullptr;
5559 if (union_type->data.unionation.gen_field_count == 0) {
5560 assert(union_type->data.unionation.gen_tag_index == SIZE_MAX);
5561 // The whole union is collapsed into the discriminant
5562 tag_field_ptr = LLVMBuildBitCast(g->builder, union_ptr,
5563 LLVMPointerType(tag_type_ref, 0), "");
5564 } else {
5565 assert(union_type->data.unionation.gen_tag_index != SIZE_MAX);
5566 tag_field_ptr = LLVMBuildStructGEP2(g->builder,
5567 get_llvm_type(g, union_type),
5568 union_ptr, union_type->data.unionation.gen_tag_index, "");
5569 }
5570
5571 LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref,
5572 &field->enum_field->value);
5573 assert(tag_field_ptr != nullptr);
5574 gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
5575
5576 return nullptr;
5577 }
5578
5579 LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr);
5580 LLVMTypeRef field_type_ref = LLVMPointerType(get_llvm_type(g, field->type_entry), 0);
5581
5582 if (union_type->data.unionation.gen_tag_index == SIZE_MAX) {
5583 LLVMValueRef union_field_ptr = LLVMBuildStructGEP2(g->builder,
5584 get_llvm_type(g, union_type), union_ptr, 0, "");
5585 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
5586 return bitcasted_union_field_ptr;
5587 }
5588
5589 if (instruction->initializing) {
5590 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP2(g->builder,
5591 get_llvm_type(g, union_type),
5592 union_ptr, union_type->data.unionation.gen_tag_index, "");
5593 LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type),
5594 &field->enum_field->value);
5595 gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
5596 } else if (instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base)) {
5597 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP2(g->builder,
5598 get_llvm_type(g, union_type),
5599 union_ptr, union_type->data.unionation.gen_tag_index, "");
5600 LLVMValueRef tag_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(tag_field_ptr),
5601 tag_field_ptr, 0, false, "");
5602
5603
5604 LLVMValueRef expected_tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type),
5605 &field->enum_field->value);
5606 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk");
5607 LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail");
5608 LLVMValueRef ok_val = LLVMBuildICmp(g->builder, LLVMIntEQ, tag_value, expected_tag_value, "");
5609 LLVMBuildCondBr(g->builder, ok_val, ok_block, bad_block);
5610
5611 LLVMPositionBuilderAtEnd(g->builder, bad_block);
5612 gen_safety_crash(g, PanicMsgIdBadUnionField);
5613
5614 LLVMPositionBuilderAtEnd(g->builder, ok_block);
5615 }
5616
5617 LLVMValueRef union_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, union_type),
5618 union_ptr, union_type->data.unionation.gen_union_index, "");
5619 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
5620 return bitcasted_union_field_ptr;
5621}
5622
5623static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_template) {
5624 const char *ptr = buf_ptr(src_template) + tok->start + 2;
5625 size_t len = tok->end - tok->start - 2;
5626 size_t result = 0;
5627 for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) {
5628 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
5629 if (buf_eql_mem(asm_output->asm_symbolic_name, ptr, len)) {
5630 return result;
5631 }
5632 }
5633 for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) {
5634 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
5635 if (buf_eql_mem(asm_input->asm_symbolic_name, ptr, len)) {
5636 return result;
5637 }
5638 }
5639 return SIZE_MAX;
5640}
5641
5642static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1AirInstAsm *instruction) {
5643 AstNode *asm_node = instruction->base.source_node;
5644 assert(asm_node->type == NodeTypeAsmExpr);
5645 AstNodeAsmExpr *asm_expr = &asm_node->data.asm_expr;
5646
5647 Buf *src_template = instruction->asm_template;
5648
5649 Buf llvm_template = BUF_INIT;
5650 buf_resize(&llvm_template, 0);
5651
5652 for (size_t token_i = 0; token_i < instruction->token_list_len; token_i += 1) {
5653 AsmToken *asm_token = &instruction->token_list[token_i];
5654 switch (asm_token->id) {
5655 case AsmTokenIdTemplate:
5656 for (size_t offset = asm_token->start; offset < asm_token->end; offset += 1) {
5657 uint8_t c = *((uint8_t*)(buf_ptr(src_template) + offset));
5658 if (c == '$') {
5659 buf_append_str(&llvm_template, "$$");
5660 } else {
5661 buf_append_char(&llvm_template, c);
5662 }
5663 }
5664 break;
5665 case AsmTokenIdPercent:
5666 buf_append_char(&llvm_template, '%');
5667 break;
5668 case AsmTokenIdVar:
5669 {
5670 size_t index = find_asm_index(g, asm_node, asm_token, src_template);
5671 assert(index < SIZE_MAX);
5672 buf_appendf(&llvm_template, "$%" ZIG_PRI_usize "", index);
5673 break;
5674 }
5675 case AsmTokenIdUniqueId:
5676 buf_append_str(&llvm_template, "${:uid}");
5677 break;
5678 }
5679 }
5680
5681 Buf constraint_buf = BUF_INIT;
5682 buf_resize(&constraint_buf, 0);
5683
5684 assert(instruction->return_count == 0 || instruction->return_count == 1);
5685
5686 size_t total_constraint_count = asm_expr->output_list.length +
5687 asm_expr->input_list.length +
5688 asm_expr->clobber_list.length;
5689 size_t input_and_output_count = asm_expr->output_list.length +
5690 asm_expr->input_list.length -
5691 instruction->return_count;
5692 size_t total_index = 0;
5693 size_t param_index = 0;
5694 LLVMTypeRef *param_types = heap::c_allocator.allocate<LLVMTypeRef>(input_and_output_count);
5695 LLVMValueRef *param_values = heap::c_allocator.allocate<LLVMValueRef>(input_and_output_count);
5696 LLVMTypeRef *param_needs_attr = heap::c_allocator.allocate<LLVMTypeRef>(input_and_output_count);
5697 for (size_t i = 0; i < asm_expr->output_list.length; i += 1, total_index += 1) {
5698 AsmOutput *asm_output = asm_expr->output_list.at(i);
5699 bool is_return = (asm_output->return_type != nullptr);
5700 assert(*buf_ptr(asm_output->constraint) == '=');
5701 // LLVM uses commas internally to separate different constraints,
5702 // alternative constraints are achieved with pipes.
5703 // We still allow the user to use commas in a way that is similar
5704 // to GCC's inline assembly.
5705 // http://llvm.org/docs/LangRef.html#constraint-codes
5706 buf_replace(asm_output->constraint, ',', '|');
5707
5708 if (is_return) {
5709 buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1);
5710 } else {
5711 buf_appendf(&constraint_buf, "=*%s", buf_ptr(asm_output->constraint) + 1);
5712 ZigVar *variable = instruction->output_vars[i];
5713 param_needs_attr[param_index] = get_llvm_type(g, variable->var_type);
5714 }
5715 if (total_index + 1 < total_constraint_count) {
5716 buf_append_char(&constraint_buf, ',');
5717 }
5718
5719 if (!is_return) {
5720 ZigVar *variable = instruction->output_vars[i];
5721 assert(variable);
5722 param_types[param_index] = LLVMTypeOf(variable->value_ref);
5723 param_values[param_index] = variable->value_ref;
5724 param_index += 1;
5725 }
5726 }
5727 for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) {
5728 AsmInput *asm_input = asm_expr->input_list.at(i);
5729 buf_replace(asm_input->constraint, ',', '|');
5730 Stage1AirInst *ir_input = instruction->input_list[i];
5731 buf_append_buf(&constraint_buf, asm_input->constraint);
5732 if (total_index + 1 < total_constraint_count) {
5733 buf_append_char(&constraint_buf, ',');
5734 }
5735
5736 ZigType *const type = ir_input->value->type;
5737 LLVMTypeRef type_ref = get_llvm_type(g, type);
5738 LLVMValueRef value_ref = ir_llvm_value(g, ir_input);
5739 LLVMTypeRef elem_type_ref = nullptr;
5740 // Handle integers of non pot bitsize by widening them.
5741 if (type->id == ZigTypeIdInt) {
5742 const size_t bitsize = type->data.integral.bit_count;
5743 if (bitsize < 8 || !is_power_of_2(bitsize)) {
5744 const bool is_signed = type->data.integral.is_signed;
5745 const size_t wider_bitsize = bitsize < 8 ? 8 : round_to_next_power_of_2(bitsize);
5746 ZigType *const wider_type = get_int_type(g, is_signed, wider_bitsize);
5747 type_ref = get_llvm_type(g, wider_type);
5748 value_ref = gen_widen_or_shorten(g, false, type, wider_type, value_ref);
5749 }
5750 } else if (handle_is_ptr(g, type)) {
5751 elem_type_ref = type_ref;
5752 ZigType *gen_type = get_pointer_to_type(g, type, true);
5753 type_ref = get_llvm_type(g, gen_type);
5754 }
5755
5756 param_types[param_index] = type_ref;
5757 param_values[param_index] = value_ref;
5758 // In the case of indirect inputs, LLVM requires the callsite to have an elementtype(<ty>) attribute.
5759 if (buf_ptr(asm_input->constraint)[0] == '*') {
5760 param_needs_attr[param_index] = elem_type_ref ? elem_type_ref :
5761 get_llvm_type(g, type->data.pointer.child_type);
5762 }
5763 }
5764 for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) {
5765 Buf *clobber_buf = asm_expr->clobber_list.at(i);
5766 buf_appendf(&constraint_buf, "~{%s}", buf_ptr(clobber_buf));
5767 if (total_index + 1 < total_constraint_count) {
5768 buf_append_char(&constraint_buf, ',');
5769 }
5770 }
5771
5772 // Add some architecture-specific clobbers.
5773 const char *arch_clobbers = nullptr;
5774 switch (g->zig_target->arch) {
5775 case ZigLLVM_x86:
5776 case ZigLLVM_x86_64:
5777 arch_clobbers = "~{dirflag},~{fpsr},~{flags}";
5778 break;
5779 case ZigLLVM_mips:
5780 case ZigLLVM_mipsel:
5781 case ZigLLVM_mips64:
5782 case ZigLLVM_mips64el:
5783 arch_clobbers = "~{$1}";
5784 break;
5785 default:
5786 break;
5787 }
5788
5789 if (arch_clobbers != nullptr) {
5790 if (buf_len(&constraint_buf))
5791 buf_append_char(&constraint_buf, ',');
5792 buf_append_str(&constraint_buf, arch_clobbers);
5793 }
5794
5795 LLVMTypeRef ret_type;
5796 if (instruction->return_count == 0) {
5797 ret_type = LLVMVoidType();
5798 } else {
5799 ret_type = get_llvm_type(g, instruction->base.value->type);
5800 }
5801 LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, (unsigned)input_and_output_count, false);
5802
5803 bool is_volatile = instruction->has_side_effects || (asm_expr->output_list.length == 0);
5804 LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(&llvm_template), buf_len(&llvm_template),
5805 buf_ptr(&constraint_buf), buf_len(&constraint_buf), is_volatile, false, LLVMInlineAsmDialectATT, false);
5806
5807 LLVMValueRef built_call = LLVMBuildCall2(g->builder, function_type,
5808 asm_fn, param_values, (unsigned)input_and_output_count, "");
5809
5810 for (size_t i = 0; i < input_and_output_count; i += 1) {
5811 if (param_needs_attr[i] != nullptr) {
5812 LLVMTypeRef elem_ty = param_needs_attr[i];
5813 ZigLLVMSetCallElemTypeAttr(built_call, i, elem_ty);
5814 }
5815 }
5816
5817
5818
5819 heap::c_allocator.deallocate(param_types, input_and_output_count);
5820 heap::c_allocator.deallocate(param_values, input_and_output_count);
5821 heap::c_allocator.deallocate(param_needs_attr, input_and_output_count);
5822 return built_call;
5823}
5824
5825static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueRef maybe_handle) {
5826 assert(maybe_type->id == ZigTypeIdOptional ||
5827 (maybe_type->id == ZigTypeIdPointer && maybe_type->data.pointer.allow_zero));
5828
5829 ZigType *child_type = maybe_type->data.maybe.child_type;
5830 if (!type_has_bits(g, child_type))
5831 return maybe_handle;
5832
5833 bool is_scalar = !handle_is_ptr(g, maybe_type);
5834 if (is_scalar)
5835 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(get_llvm_type(g, maybe_type)), "");
5836
5837 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP2(g->builder,
5838 get_llvm_type(g, maybe_type), maybe_handle, maybe_null_index, "");
5839 return gen_load_untyped(g, ZigLLVMGetGEPResultElementType(maybe_field_ptr), maybe_field_ptr, 0, false, "");
5840}
5841
5842static LLVMValueRef ir_render_test_non_null(CodeGen *g, Stage1Air *executable,
5843 Stage1AirInstTestNonNull *instruction)
5844{
5845 return gen_non_null_bit(g, instruction->value->value->type, ir_llvm_value(g, instruction->value));
5846}
5847
5848static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, Stage1Air *executable,
5849 Stage1AirInstOptionalUnwrapPtr *instruction)
5850{
5851 if (instruction->base.value->special != ConstValSpecialRuntime)
5852 return nullptr;
5853
5854 ZigType *ptr_type = instruction->base_ptr->value->type;
5855 assert(ptr_type->id == ZigTypeIdPointer);
5856 ZigType *maybe_type = ptr_type->data.pointer.child_type;
5857 assert(maybe_type->id == ZigTypeIdOptional);
5858 ZigType *child_type = maybe_type->data.maybe.child_type;
5859 LLVMValueRef base_ptr = ir_llvm_value(g, instruction->base_ptr);
5860 if (instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base)) {
5861 LLVMValueRef maybe_handle = get_handle_value(g, base_ptr, maybe_type, ptr_type);
5862 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
5863 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
5864 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
5865 LLVMBuildCondBr(g->builder, non_null_bit, ok_block, fail_block);
5866
5867 LLVMPositionBuilderAtEnd(g->builder, fail_block);
5868 gen_safety_crash(g, PanicMsgIdUnwrapOptionalFail);
5869
5870 LLVMPositionBuilderAtEnd(g->builder, ok_block);
5871 }
5872 if (!type_has_bits(g, child_type)) {
5873 if (instruction->initializing) {
5874 LLVMValueRef non_null_bit = LLVMConstInt(LLVMInt1Type(), 1, false);
5875 gen_store_untyped(g, non_null_bit, base_ptr, 0, false);
5876 }
5877 return nullptr;
5878 } else {
5879 bool is_scalar = !handle_is_ptr(g, maybe_type);
5880 if (is_scalar) {
5881 return base_ptr;
5882 } else {
5883 LLVMValueRef optional_struct_ref = get_handle_value(g, base_ptr, maybe_type, ptr_type);
5884 if (instruction->initializing) {
5885 LLVMValueRef non_null_bit_ptr = LLVMBuildStructGEP2(g->builder,
5886 get_llvm_type(g, maybe_type), optional_struct_ref, maybe_null_index, "");
5887 LLVMValueRef non_null_bit = LLVMConstInt(LLVMInt1Type(), 1, false);
5888 gen_store_untyped(g, non_null_bit, non_null_bit_ptr, 0, false);
5889 }
5890 return LLVMBuildStructGEP2(g->builder,
5891 get_llvm_type(g, maybe_type), optional_struct_ref, maybe_child_index, "");
5892 }
5893 }
5894}
5895
5896static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *expr_type, BuiltinFnId fn_id) {
5897 bool is_vector = expr_type->id == ZigTypeIdVector;
5898 ZigType *int_type = is_vector ? expr_type->data.vector.elem_type : expr_type;
5899 assert(int_type->id == ZigTypeIdInt);
5900 uint32_t vector_len = is_vector ? expr_type->data.vector.len : 0;
5901 ZigLLVMFnKey key = {};
5902 const char *fn_name;
5903 uint32_t n_args;
5904 if (fn_id == BuiltinFnIdCtz) {
5905 fn_name = "cttz";
5906 n_args = 2;
5907 key.id = ZigLLVMFnIdCtz;
5908 key.data.ctz.bit_count = (uint32_t)int_type->data.integral.bit_count;
5909 key.data.ctz.vector_len = vector_len;
5910 } else if (fn_id == BuiltinFnIdClz) {
5911 fn_name = "ctlz";
5912 n_args = 2;
5913 key.id = ZigLLVMFnIdClz;
5914 key.data.clz.bit_count = (uint32_t)int_type->data.integral.bit_count;
5915 key.data.clz.vector_len = vector_len;
5916 } else if (fn_id == BuiltinFnIdPopCount) {
5917 fn_name = "ctpop";
5918 n_args = 1;
5919 key.id = ZigLLVMFnIdPopCount;
5920 key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count;
5921 key.data.pop_count.vector_len = vector_len;
5922 } else if (fn_id == BuiltinFnIdBswap) {
5923 fn_name = "bswap";
5924 n_args = 1;
5925 key.id = ZigLLVMFnIdBswap;
5926 key.data.bswap.bit_count = (uint32_t)int_type->data.integral.bit_count;
5927 key.data.bswap.vector_len = vector_len;
5928 } else if (fn_id == BuiltinFnIdBitReverse) {
5929 fn_name = "bitreverse";
5930 n_args = 1;
5931 key.id = ZigLLVMFnIdBitReverse;
5932 key.data.bit_reverse.bit_count = (uint32_t)int_type->data.integral.bit_count;
5933 key.data.bit_reverse.vector_len = vector_len;
5934 } else {
5935 zig_unreachable();
5936 }
5937
5938 auto existing_entry = g->llvm_fn_table.maybe_get(key);
5939 if (existing_entry)
5940 return existing_entry->value;
5941
5942 char llvm_name[64];
5943 if (is_vector)
5944 snprintf(llvm_name, sizeof(llvm_name), "llvm.%s.v%" PRIu32 "i%" PRIu32, fn_name, vector_len, int_type->data.integral.bit_count);
5945 else
5946 snprintf(llvm_name, sizeof(llvm_name), "llvm.%s.i%" PRIu32, fn_name, int_type->data.integral.bit_count);
5947 LLVMTypeRef param_types[] = {
5948 get_llvm_type(g, expr_type),
5949 LLVMInt1Type(),
5950 };
5951 LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, expr_type), param_types, n_args, false);
5952 LLVMValueRef fn_val = LLVMAddFunction(g->module, llvm_name, fn_type);
5953 assert(LLVMGetIntrinsicID(fn_val));
5954
5955 g->llvm_fn_table.put(key, fn_val);
5956
5957 return fn_val;
5958}
5959
5960static LLVMValueRef ir_render_clz(CodeGen *g, Stage1Air *executable, Stage1AirInstClz *instruction) {
5961 ZigType *int_type = instruction->op->value->type;
5962 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdClz);
5963 LLVMValueRef operand = ir_llvm_value(g, instruction->op);
5964 LLVMValueRef params[] {
5965 operand,
5966 LLVMConstNull(LLVMInt1Type()),
5967 };
5968 LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, "");
5969 return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int);
5970}
5971
5972static LLVMValueRef ir_render_ctz(CodeGen *g, Stage1Air *executable, Stage1AirInstCtz *instruction) {
5973 ZigType *int_type = instruction->op->value->type;
5974 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdCtz);
5975 LLVMValueRef operand = ir_llvm_value(g, instruction->op);
5976 LLVMValueRef params[] {
5977 operand,
5978 LLVMConstNull(LLVMInt1Type()),
5979 };
5980 LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, "");
5981 return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int);
5982}
5983
5984static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, Stage1Air *executable, Stage1AirInstShuffleVector *instruction) {
5985 uint64_t len_a = instruction->a->value->type->data.vector.len;
5986 uint64_t len_mask = instruction->mask->value->type->data.vector.len;
5987
5988 // LLVM uses integers larger than the length of the first array to
5989 // index into the second array. This was deemed unnecessarily fragile
5990 // when changing code, so Zig uses negative numbers to index the
5991 // second vector. These start at -1 and go down, and are easiest to use
5992 // with the ~ operator. Here we convert between the two formats.
5993 Stage1AirInst *mask = instruction->mask;
5994 LLVMValueRef *values = heap::c_allocator.allocate<LLVMValueRef>(len_mask);
5995 for (uint64_t i = 0; i < len_mask; i++) {
5996 if (mask->value->data.x_array.data.s_none.elements[i].special == ConstValSpecialUndef) {
5997 values[i] = LLVMGetUndef(LLVMInt32Type());
5998 } else {
5999 int32_t v = bigint_as_signed(&mask->value->data.x_array.data.s_none.elements[i].data.x_bigint);
6000 uint32_t index_val = (v >= 0) ? (uint32_t)v : (uint32_t)~v + (uint32_t)len_a;
6001 values[i] = LLVMConstInt(LLVMInt32Type(), index_val, false);
6002 }
6003 }
6004
6005 LLVMValueRef llvm_mask_value = LLVMConstVector(values, len_mask);
6006 heap::c_allocator.deallocate(values, len_mask);
6007
6008 return LLVMBuildShuffleVector(g->builder,
6009 ir_llvm_value(g, instruction->a),
6010 ir_llvm_value(g, instruction->b),
6011 llvm_mask_value, "");
6012}
6013
6014static LLVMValueRef ir_render_select(CodeGen *g, Stage1Air *executable, Stage1AirInstSelect *instruction) {
6015 LLVMValueRef pred = ir_llvm_value(g, instruction->pred);
6016 LLVMValueRef a = ir_llvm_value(g, instruction->a);
6017 LLVMValueRef b = ir_llvm_value(g, instruction->b);
6018 return LLVMBuildSelect(g->builder, pred, a, b, "");
6019}
6020
6021static LLVMValueRef ir_render_splat(CodeGen *g, Stage1Air *executable, Stage1AirInstSplat *instruction) {
6022 ZigType *result_type = instruction->base.value->type;
6023 ir_assert(result_type->id == ZigTypeIdVector, &instruction->base);
6024 uint32_t len = result_type->data.vector.len;
6025 LLVMTypeRef op_llvm_type = LLVMVectorType(get_llvm_type(g, instruction->scalar->value->type), 1);
6026 LLVMTypeRef mask_llvm_type = LLVMVectorType(LLVMInt32Type(), len);
6027 LLVMValueRef undef_vector = LLVMGetUndef(op_llvm_type);
6028 LLVMValueRef op_vector = LLVMBuildInsertElement(g->builder, undef_vector,
6029 ir_llvm_value(g, instruction->scalar), LLVMConstInt(LLVMInt32Type(), 0, false), "");
6030 return LLVMBuildShuffleVector(g->builder, op_vector, undef_vector, LLVMConstNull(mask_llvm_type), "");
6031}
6032
6033static LLVMValueRef ir_render_pop_count(CodeGen *g, Stage1Air *executable, Stage1AirInstPopCount *instruction) {
6034 ZigType *int_type = instruction->op->value->type;
6035 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount);
6036 LLVMValueRef operand = ir_llvm_value(g, instruction->op);
6037 LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &operand, 1, "");
6038 return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int);
6039}
6040
6041static LLVMValueRef ir_render_switch_br(CodeGen *g, Stage1Air *executable, Stage1AirInstSwitchBr *instruction) {
6042 ZigType *target_type = instruction->target_value->value->type;
6043 LLVMBasicBlockRef else_block = instruction->else_block->llvm_block;
6044
6045 LLVMValueRef target_value = ir_llvm_value(g, instruction->target_value);
6046 if (target_type->id == ZigTypeIdPointer) {
6047 const ZigType *usize = g->builtin_types.entry_usize;
6048 target_value = LLVMBuildPtrToInt(g->builder, target_value, usize->llvm_type, "");
6049 }
6050
6051 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, target_value, else_block,
6052 (unsigned)instruction->case_count);
6053
6054 for (size_t i = 0; i < instruction->case_count; i += 1) {
6055 Stage1AirInstSwitchBrCase *this_case = &instruction->cases[i];
6056
6057 LLVMValueRef case_value = ir_llvm_value(g, this_case->value);
6058 if (target_type->id == ZigTypeIdPointer) {
6059 const ZigType *usize = g->builtin_types.entry_usize;
6060 case_value = LLVMBuildPtrToInt(g->builder, case_value, usize->llvm_type, "");
6061 }
6062
6063 LLVMAddCase(switch_instr, case_value, this_case->block->llvm_block);
6064 }
6065
6066 return nullptr;
6067}
6068
6069static LLVMValueRef ir_render_phi(CodeGen *g, Stage1Air *executable, Stage1AirInstPhi *instruction) {
6070 if (!type_has_bits(g, instruction->base.value->type))
6071 return nullptr;
6072
6073 LLVMTypeRef phi_type;
6074 if (handle_is_ptr(g, instruction->base.value->type)) {
6075 phi_type = LLVMPointerType(get_llvm_type(g,instruction->base.value->type), 0);
6076 } else {
6077 phi_type = get_llvm_type(g, instruction->base.value->type);
6078 }
6079
6080 LLVMValueRef phi = LLVMBuildPhi(g->builder, phi_type, "");
6081 LLVMValueRef *incoming_values = heap::c_allocator.allocate<LLVMValueRef>(instruction->incoming_count);
6082 LLVMBasicBlockRef *incoming_blocks = heap::c_allocator.allocate<LLVMBasicBlockRef>(instruction->incoming_count);
6083 for (size_t i = 0; i < instruction->incoming_count; i += 1) {
6084 incoming_values[i] = ir_llvm_value(g, instruction->incoming_values[i]);
6085 incoming_blocks[i] = instruction->incoming_blocks[i]->llvm_exit_block;
6086 }
6087 LLVMAddIncoming(phi, incoming_values, incoming_blocks, (unsigned)instruction->incoming_count);
6088 heap::c_allocator.deallocate(incoming_values, instruction->incoming_count);
6089 heap::c_allocator.deallocate(incoming_blocks, instruction->incoming_count);
6090 return phi;
6091}
6092
6093static LLVMValueRef ir_render_ref(CodeGen *g, Stage1Air *executable, Stage1AirInstRef *instruction) {
6094 if (!type_has_bits(g, instruction->base.value->type)) {
6095 return nullptr;
6096 }
6097 if (instruction->operand->id == Stage1AirInstIdCall) {
6098 Stage1AirInstCall *call = reinterpret_cast<Stage1AirInstCall *>(instruction->operand);
6099 if (call->result_loc != nullptr) {
6100 return ir_llvm_value(g, call->result_loc);
6101 }
6102 }
6103 LLVMValueRef value = ir_llvm_value(g, instruction->operand);
6104 if (handle_is_ptr(g, instruction->operand->value->type)) {
6105 return value;
6106 } else {
6107 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
6108 gen_store_untyped(g, value, result_loc, 0, false);
6109 return result_loc;
6110 }
6111}
6112
6113static LLVMValueRef ir_render_err_name(CodeGen *g, Stage1Air *executable, Stage1AirInstErrName *instruction) {
6114 assert(g->generate_error_name_table);
6115 assert(g->errors_by_index.length > 0);
6116
6117 LLVMValueRef err_val = ir_llvm_value(g, instruction->value);
6118 if (ir_want_runtime_safety(g, &instruction->base)) {
6119 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val));
6120 LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->errors_by_index.length, false);
6121 add_bounds_check(g, err_val, LLVMIntNE, zero, LLVMIntULT, end_val);
6122 }
6123
6124 LLVMValueRef indices[] = {
6125 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
6126 err_val,
6127 };
6128 return LLVMBuildInBoundsGEP2(g->builder,
6129 LLVMGlobalGetValueType(g->err_name_table),
6130 g->err_name_table, indices, 2, "");
6131}
6132
6133static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {
6134 assert(enum_type->id == ZigTypeIdEnum);
6135 if (enum_type->data.enumeration.name_function)
6136 return enum_type->data.enumeration.name_function;
6137
6138 ZigType *u8_ptr_type = get_pointer_to_type_extra2(g, g->builtin_types.entry_u8, false, false,
6139 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false,
6140 VECTOR_INDEX_NONE, nullptr, g->intern.for_zero_byte());
6141 ZigType *u8_slice_type = get_slice_type(g, u8_ptr_type);
6142 ZigType *tag_int_type = enum_type->data.enumeration.tag_int_type;
6143
6144 LLVMTypeRef tag_int_llvm_type = get_llvm_type(g, tag_int_type);
6145 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(get_llvm_type(g, u8_slice_type), 0),
6146 &tag_int_llvm_type, 1, false);
6147
6148 const char *fn_name = get_mangled_name(g,
6149 buf_ptr(buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name))));
6150 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref);
6151 LLVMSetLinkage(fn_val, LLVMInternalLinkage);
6152 ZigLLVMFunctionSetCallingConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
6153 add_common_fn_attributes(g, fn_val);
6154 if (!g->omit_frame_pointer) {
6155 ZigLLVMAddFunctionAttr(fn_val, "frame-pointer", "all");
6156 }
6157
6158 LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder);
6159 LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder);
6160 ZigFn *prev_cur_fn = g->cur_fn;
6161 LLVMValueRef prev_cur_fn_val = g->cur_fn_val;
6162
6163 LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry");
6164 LLVMPositionBuilderAtEnd(g->builder, entry_block);
6165 ZigLLVMClearCurrentDebugLocation(g->builder);
6166 g->cur_fn = nullptr;
6167 g->cur_fn_val = fn_val;
6168
6169 size_t field_count = enum_type->data.enumeration.src_field_count;
6170 LLVMBasicBlockRef bad_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadValue");
6171 LLVMValueRef tag_int_value = LLVMGetParam(fn_val, 0);
6172 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, tag_int_value, bad_value_block, field_count);
6173
6174
6175 ZigType *usize = g->builtin_types.entry_usize;
6176 LLVMValueRef array_ptr_indices[] = {
6177 LLVMConstNull(usize->llvm_type),
6178 LLVMConstNull(usize->llvm_type),
6179 };
6180
6181 HashMap<BigInt, Buf *, bigint_hash, bigint_eql> occupied_tag_values = {};
6182 occupied_tag_values.init(field_count);
6183
6184 for (size_t field_i = 0; field_i < field_count; field_i += 1) {
6185 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
6186
6187 Buf *name = type_enum_field->name;
6188 auto entry = occupied_tag_values.put_unique(type_enum_field->value, name);
6189 if (entry != nullptr) {
6190 continue;
6191 }
6192
6193 LLVMValueRef str_init = LLVMConstString(buf_ptr(name), (unsigned)buf_len(name), false);
6194 LLVMValueRef str_global = LLVMAddGlobal(g->module, LLVMTypeOf(str_init), "");
6195 LLVMSetInitializer(str_global, str_init);
6196 LLVMSetLinkage(str_global, LLVMPrivateLinkage);
6197 LLVMSetGlobalConstant(str_global, true);
6198 LLVMSetUnnamedAddr(str_global, true);
6199 LLVMSetAlignment(str_global, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(str_init)));
6200
6201 LLVMValueRef fields[] = {
6202 LLVMConstInBoundsGEP2(LLVMGlobalGetValueType(str_global), str_global, array_ptr_indices, 2),
6203 LLVMConstInt(g->builtin_types.entry_usize->llvm_type, buf_len(name), false),
6204 };
6205 LLVMValueRef slice_init_value = LLVMConstNamedStruct(get_llvm_type(g, u8_slice_type), fields, 2);
6206
6207 LLVMValueRef slice_global = LLVMAddGlobal(g->module, LLVMTypeOf(slice_init_value), "");
6208 LLVMSetInitializer(slice_global, slice_init_value);
6209 LLVMSetLinkage(slice_global, LLVMPrivateLinkage);
6210 LLVMSetGlobalConstant(slice_global, true);
6211 LLVMSetUnnamedAddr(slice_global, true);
6212 LLVMSetAlignment(slice_global, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(slice_init_value)));
6213
6214 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn_val, "Name");
6215 LLVMValueRef this_tag_int_value = bigint_to_llvm_const(get_llvm_type(g, tag_int_type),
6216 &enum_type->data.enumeration.fields[field_i].value);
6217 LLVMAddCase(switch_instr, this_tag_int_value, return_block);
6218
6219 LLVMPositionBuilderAtEnd(g->builder, return_block);
6220 LLVMBuildRet(g->builder, slice_global);
6221 }
6222 occupied_tag_values.deinit();
6223
6224 LLVMPositionBuilderAtEnd(g->builder, bad_value_block);
6225 if (g->build_mode == BuildModeDebug || g->build_mode == BuildModeSafeRelease) {
6226 gen_safety_crash(g, PanicMsgIdBadEnumValue);
6227 } else {
6228 LLVMBuildUnreachable(g->builder);
6229 }
6230
6231 g->cur_fn = prev_cur_fn;
6232 g->cur_fn_val = prev_cur_fn_val;
6233 LLVMPositionBuilderAtEnd(g->builder, prev_block);
6234 if (!g->strip_debug_symbols) {
6235 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
6236 }
6237
6238 enum_type->data.enumeration.name_function = fn_val;
6239 return fn_val;
6240}
6241
6242static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, Stage1Air *executable,
6243 Stage1AirInstTagName *instruction)
6244{
6245 ZigType *enum_type = instruction->target->value->type;
6246 assert(enum_type->id == ZigTypeIdEnum);
6247
6248 LLVMValueRef enum_name_function = get_enum_tag_name_function(g, enum_type);
6249
6250 LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target);
6251 return ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(enum_name_function), enum_name_function,
6252 &enum_tag_value, 1,
6253 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
6254}
6255
6256static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, Stage1Air *executable,
6257 Stage1AirInstFieldParentPtr *instruction)
6258{
6259 ZigType *container_ptr_type = instruction->base.value->type;
6260 assert(container_ptr_type->id == ZigTypeIdPointer);
6261
6262 ZigType *container_type = container_ptr_type->data.pointer.child_type;
6263
6264 size_t byte_offset = LLVMOffsetOfElement(g->target_data_ref,
6265 get_llvm_type(g, container_type), instruction->field->gen_index);
6266
6267 LLVMValueRef field_ptr_val = ir_llvm_value(g, instruction->field_ptr);
6268
6269 if (byte_offset == 0) {
6270 return LLVMBuildBitCast(g->builder, field_ptr_val, get_llvm_type(g, container_ptr_type), "");
6271 } else {
6272 ZigType *usize = g->builtin_types.entry_usize;
6273
6274 LLVMValueRef field_ptr_int = LLVMBuildPtrToInt(g->builder, field_ptr_val, usize->llvm_type, "");
6275
6276 LLVMValueRef base_ptr_int = LLVMBuildNUWSub(g->builder, field_ptr_int,
6277 LLVMConstInt(usize->llvm_type, byte_offset, false), "");
6278
6279 return LLVMBuildIntToPtr(g->builder, base_ptr_int, get_llvm_type(g, container_ptr_type), "");
6280 }
6281}
6282
6283static LLVMValueRef ir_render_align_cast(CodeGen *g, Stage1Air *executable, Stage1AirInstAlignCast *instruction) {
6284 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
6285 assert(target_val);
6286
6287 bool want_runtime_safety = ir_want_runtime_safety(g, &instruction->base);
6288 if (!want_runtime_safety) {
6289 return target_val;
6290 }
6291
6292 ZigType *target_type = instruction->base.value->type;
6293 uint32_t align_bytes;
6294 LLVMValueRef ptr_val;
6295
6296 if (target_type->id == ZigTypeIdPointer) {
6297 align_bytes = get_ptr_align(g, target_type);
6298 ptr_val = target_val;
6299 } else if (target_type->id == ZigTypeIdFn) {
6300 align_bytes = target_type->data.fn.fn_type_id.alignment;
6301 ptr_val = target_val;
6302 } else if (target_type->id == ZigTypeIdOptional &&
6303 target_type->data.maybe.child_type->id == ZigTypeIdPointer)
6304 {
6305 align_bytes = get_ptr_align(g, target_type->data.maybe.child_type);
6306 ptr_val = target_val;
6307 } else if (target_type->id == ZigTypeIdOptional &&
6308 target_type->data.maybe.child_type->id == ZigTypeIdFn)
6309 {
6310 align_bytes = target_type->data.maybe.child_type->data.fn.fn_type_id.alignment;
6311 ptr_val = target_val;
6312 } else if (target_type->id == ZigTypeIdStruct &&
6313 target_type->data.structure.special == StructSpecialSlice)
6314 {
6315 ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index]->type_entry;
6316 align_bytes = get_ptr_align(g, slice_ptr_type);
6317
6318 size_t ptr_index = target_type->data.structure.fields[slice_ptr_index]->gen_index;
6319 LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP2(g->builder,
6320 get_llvm_type(g, target_type),
6321 target_val, (unsigned)ptr_index, "");
6322 ptr_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_val_ptr), ptr_val_ptr, 0, false, "");
6323 } else {
6324 zig_unreachable();
6325 }
6326
6327 assert(align_bytes != 1);
6328
6329 ZigType *usize = g->builtin_types.entry_usize;
6330 LLVMValueRef ptr_as_int_val = LLVMBuildPtrToInt(g->builder, ptr_val, usize->llvm_type, "");
6331 LLVMValueRef alignment_minus_1 = LLVMConstInt(usize->llvm_type, align_bytes - 1, false);
6332 LLVMValueRef anded_val = LLVMBuildAnd(g->builder, ptr_as_int_val, alignment_minus_1, "");
6333 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, anded_val, LLVMConstNull(usize->llvm_type), "");
6334
6335 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "AlignCastOk");
6336 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "AlignCastFail");
6337
6338 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
6339
6340 LLVMPositionBuilderAtEnd(g->builder, fail_block);
6341 gen_safety_crash(g, PanicMsgIdIncorrectAlignment);
6342
6343 LLVMPositionBuilderAtEnd(g->builder, ok_block);
6344
6345 return target_val;
6346}
6347
6348static LLVMValueRef ir_render_error_return_trace(CodeGen *g, Stage1Air *executable,
6349 Stage1AirInstErrorReturnTrace *instruction)
6350{
6351 bool is_llvm_alloca;
6352 LLVMValueRef cur_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca);
6353 if (cur_err_ret_trace_val == nullptr) {
6354 return LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type(g)));
6355 }
6356 return cur_err_ret_trace_val;
6357}
6358
6359static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {
6360 switch (atomic_order) {
6361 case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered;
6362 case AtomicOrderMonotonic: return LLVMAtomicOrderingMonotonic;
6363 case AtomicOrderAcquire: return LLVMAtomicOrderingAcquire;
6364 case AtomicOrderRelease: return LLVMAtomicOrderingRelease;
6365 case AtomicOrderAcqRel: return LLVMAtomicOrderingAcquireRelease;
6366 case AtomicOrderSeqCst: return LLVMAtomicOrderingSequentiallyConsistent;
6367 }
6368 zig_unreachable();
6369}
6370
6371static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed, bool is_float) {
6372 switch (op) {
6373 case AtomicRmwOp_xchg: return LLVMAtomicRMWBinOpXchg;
6374 case AtomicRmwOp_add:
6375 return is_float ? LLVMAtomicRMWBinOpFAdd : LLVMAtomicRMWBinOpAdd;
6376 case AtomicRmwOp_sub:
6377 return is_float ? LLVMAtomicRMWBinOpFSub : LLVMAtomicRMWBinOpSub;
6378 case AtomicRmwOp_and: return LLVMAtomicRMWBinOpAnd;
6379 case AtomicRmwOp_nand: return LLVMAtomicRMWBinOpNand;
6380 case AtomicRmwOp_or: return LLVMAtomicRMWBinOpOr;
6381 case AtomicRmwOp_xor: return LLVMAtomicRMWBinOpXor;
6382 case AtomicRmwOp_max:
6383 return is_signed ? LLVMAtomicRMWBinOpMax : LLVMAtomicRMWBinOpUMax;
6384 case AtomicRmwOp_min:
6385 return is_signed ? LLVMAtomicRMWBinOpMin : LLVMAtomicRMWBinOpUMin;
6386 }
6387 zig_unreachable();
6388}
6389
6390static LLVMTypeRef get_atomic_abi_type(CodeGen *g, Stage1AirInst *instruction, bool RMWXchg) {
6391 // If the operand type of an atomic operation is not byte sized we need to
6392 // widen it before using it and then truncate the result.
6393 // RMW exchange of floating-point values is bitcasted to same-sized integer
6394 // types to work around a LLVM deficiency when targeting ARM/AArch64.
6395
6396 ir_assert(instruction->value->type->id == ZigTypeIdPointer, instruction);
6397 ZigType *operand_type = instruction->value->type->data.pointer.child_type;
6398 if (operand_type->id == ZigTypeIdInt || operand_type->id == ZigTypeIdEnum) {
6399 if (operand_type->id == ZigTypeIdEnum) {
6400 operand_type = operand_type->data.enumeration.tag_int_type;
6401 }
6402 auto bit_count = operand_type->data.integral.bit_count;
6403 bool is_signed = operand_type->data.integral.is_signed;
6404
6405 ir_assert(bit_count != 0, instruction);
6406 if (!is_power_of_2(bit_count) || bit_count % 8) {
6407 return get_llvm_type(g, get_int_type(g, is_signed, operand_type->abi_size * 8));
6408 } else {
6409 return nullptr;
6410 }
6411 } else if (operand_type->id == ZigTypeIdFloat) {
6412 return RMWXchg ? LLVMIntType(operand_type->abi_size * 8) : nullptr;
6413 } else if (operand_type->id == ZigTypeIdBool) {
6414 return g->builtin_types.entry_u8->llvm_type;
6415 } else {
6416 ir_assert(get_codegen_ptr_type_bail(g, operand_type) != nullptr, instruction);
6417 return nullptr;
6418 }
6419}
6420
6421static LLVMValueRef ir_render_cmpxchg(CodeGen *g, Stage1Air *executable, Stage1AirInstCmpxchg *instruction) {
6422 LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);
6423 LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
6424 LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
6425
6426 ZigType *operand_type = instruction->new_value->value->type;
6427 LLVMTypeRef actual_abi_type = get_atomic_abi_type(g, instruction->ptr, false);
6428 if (actual_abi_type != nullptr) {
6429 // operand needs widening and truncating
6430 ptr_val = LLVMBuildBitCast(g->builder, ptr_val,
6431 LLVMPointerType(actual_abi_type, 0), "");
6432 if (operand_type->data.integral.is_signed) {
6433 cmp_val = LLVMBuildSExt(g->builder, cmp_val, actual_abi_type, "");
6434 new_val = LLVMBuildSExt(g->builder, new_val, actual_abi_type, "");
6435 } else {
6436 cmp_val = LLVMBuildZExt(g->builder, cmp_val, actual_abi_type, "");
6437 new_val = LLVMBuildZExt(g->builder, new_val, actual_abi_type, "");
6438 }
6439 }
6440
6441 LLVMAtomicOrdering success_order = to_LLVMAtomicOrdering(instruction->success_order);
6442 LLVMAtomicOrdering failure_order = to_LLVMAtomicOrdering(instruction->failure_order);
6443
6444 LLVMValueRef result_val = LLVMBuildAtomicCmpXchg(g->builder, ptr_val, cmp_val, new_val,
6445 success_order, failure_order, g->is_single_threaded);
6446 LLVMSetWeak(result_val, instruction->is_weak);
6447
6448 ZigType *optional_type = instruction->base.value->type;
6449 assert(optional_type->id == ZigTypeIdOptional);
6450 ZigType *child_type = optional_type->data.maybe.child_type;
6451
6452 if (!handle_is_ptr(g, optional_type)) {
6453 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
6454 if (actual_abi_type != nullptr) {
6455 payload_val = LLVMBuildTrunc(g->builder, payload_val, get_llvm_type(g, operand_type), "");
6456 }
6457 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
6458 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");
6459 }
6460
6461 // When the cmpxchg is discarded, the result location will have no bits.
6462 if (!type_has_bits(g, instruction->result_loc->value->type)) {
6463 return nullptr;
6464 }
6465
6466 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
6467 ir_assert(result_loc != nullptr, &instruction->base);
6468 ir_assert(type_has_bits(g, child_type), &instruction->base);
6469
6470 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
6471 if (actual_abi_type != nullptr) {
6472 payload_val = LLVMBuildTrunc(g->builder, payload_val, get_llvm_type(g, operand_type), "");
6473 }
6474 LLVMTypeRef result_loc_struct_llvm_ty = get_llvm_type(g,
6475 instruction->result_loc->value->type->data.pointer.child_type);
6476 LLVMValueRef val_ptr = LLVMBuildStructGEP2(g->builder,
6477 result_loc_struct_llvm_ty, result_loc, maybe_child_index, "");
6478 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
6479
6480 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
6481 LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
6482 LLVMValueRef maybe_ptr = LLVMBuildStructGEP2(g->builder, result_loc_struct_llvm_ty, result_loc,
6483 maybe_null_index, "");
6484 gen_store_untyped(g, nonnull_bit, maybe_ptr, 0, false);
6485 return result_loc;
6486}
6487
6488static LLVMValueRef ir_render_reduced_call(CodeGen *g, LLVMValueRef llvm_fn, LLVMValueRef operand_vector, size_t vector_len, LLVMValueRef accum_init, ZigType *accum_ty) {
6489 LLVMTypeRef llvm_usize_ty = g->builtin_types.entry_usize->llvm_type;
6490 LLVMValueRef llvm_vector_len = LLVMConstInt(llvm_usize_ty, vector_len, false);
6491 LLVMTypeRef llvm_result_ty = LLVMTypeOf(accum_init);
6492
6493 // Allocate and initialize our mutable variables
6494 LLVMValueRef i_ptr = build_alloca(g, g->builtin_types.entry_usize, "i", 0);
6495 LLVMBuildStore(g->builder, LLVMConstInt(llvm_usize_ty, 0, false), i_ptr);
6496 LLVMValueRef accum_ptr = build_alloca(g, accum_ty, "accum", 0);
6497 LLVMBuildStore(g->builder, accum_init, accum_ptr);
6498
6499 // Setup the loop
6500 LLVMBasicBlockRef loop = LLVMAppendBasicBlock(g->cur_fn_val, "ReduceLoop");
6501 LLVMBasicBlockRef loop_exit = LLVMAppendBasicBlock(g->cur_fn_val, "AfterReduce");
6502 LLVMBuildBr(g->builder, loop);
6503 {
6504 LLVMPositionBuilderAtEnd(g->builder, loop);
6505
6506 // while (i < vec.len)
6507 LLVMValueRef i = LLVMBuildLoad2(g->builder, llvm_usize_ty, i_ptr, "");
6508 LLVMValueRef cond = LLVMBuildICmp(g->builder, LLVMIntULT, i, llvm_vector_len, "");
6509 LLVMBasicBlockRef loop_then = LLVMAppendBasicBlock(g->cur_fn_val, "ReduceLoopThen");
6510
6511 LLVMBuildCondBr(g->builder, cond, loop_then, loop_exit);
6512
6513 {
6514 LLVMPositionBuilderAtEnd(g->builder, loop_then);
6515
6516 // accum = f(accum, vec[i]);
6517 LLVMValueRef accum = LLVMBuildLoad2(g->builder, llvm_result_ty, accum_ptr, "");
6518 LLVMValueRef element = LLVMBuildExtractElement(g->builder, operand_vector, i, "");
6519 LLVMValueRef params[] {
6520 accum,
6521 element
6522 };
6523 LLVMValueRef new_accum = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(llvm_fn), llvm_fn, params, 2, "");
6524 LLVMBuildStore(g->builder, new_accum, accum_ptr);
6525
6526 // i += 1
6527 LLVMValueRef new_i = LLVMBuildAdd(g->builder, i, LLVMConstInt(llvm_usize_ty, 1, false), "");
6528 LLVMBuildStore(g->builder, new_i, i_ptr);
6529 LLVMBuildBr(g->builder, loop);
6530 }
6531 }
6532
6533 LLVMPositionBuilderAtEnd(g->builder, loop_exit);
6534 return LLVMBuildLoad2(g->builder, llvm_result_ty, accum_ptr, "");
6535}
6536
6537static LLVMValueRef ir_render_reduce(CodeGen *g, Stage1Air *executable, Stage1AirInstReduce *instruction) {
6538 LLVMValueRef value = ir_llvm_value(g, instruction->value);
6539
6540 ZigType *value_type = instruction->value->value->type;
6541 assert(value_type->id == ZigTypeIdVector);
6542 ZigType *scalar_type = value_type->data.vector.elem_type;
6543
6544 bool float_intrinsics_allowed = true;
6545 const char *compiler_rt_type_abbrev = nullptr;
6546 const char *math_float_prefix = nullptr;
6547 const char *math_float_suffix = nullptr;
6548 if ((scalar_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) ||
6549 (scalar_type == g->builtin_types.entry_f128 && !target_long_double_is_f128(g->zig_target)) ||
6550 (scalar_type == g->builtin_types.entry_f16 && !target_is_arm(g->zig_target))) {
6551 float_intrinsics_allowed = false;
6552 compiler_rt_type_abbrev = get_compiler_rt_type_abbrev(scalar_type);
6553 math_float_prefix = libc_float_prefix(g, scalar_type);
6554 math_float_suffix = libc_float_suffix(g, scalar_type);
6555 }
6556
6557 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &instruction->base));
6558
6559 char fn_name[64];
6560 ZigValue *init_value = nullptr;
6561 switch (instruction->op) {
6562 case ReduceOp_and:
6563 assert(scalar_type->id == ZigTypeIdInt || scalar_type->id == ZigTypeIdBool);
6564 return ZigLLVMBuildAndReduce(g->builder, value);
6565 break;
6566 case ReduceOp_or:
6567 assert(scalar_type->id == ZigTypeIdInt || scalar_type->id == ZigTypeIdBool);
6568 return ZigLLVMBuildOrReduce(g->builder, value);
6569 break;
6570 case ReduceOp_xor:
6571 assert(scalar_type->id == ZigTypeIdInt || scalar_type->id == ZigTypeIdBool);
6572 return ZigLLVMBuildXorReduce(g->builder, value);
6573 break;
6574 case ReduceOp_min: {
6575 if (scalar_type->id == ZigTypeIdInt) {
6576 const bool is_signed = scalar_type->data.integral.is_signed;
6577 return ZigLLVMBuildIntMinReduce(g->builder, value, is_signed);
6578 } else if (scalar_type->id == ZigTypeIdFloat) {
6579 if (float_intrinsics_allowed) {
6580 return ZigLLVMBuildFPMinReduce(g->builder, value);
6581 } else {
6582 snprintf(fn_name, sizeof(fn_name), "%sfmin%s", math_float_prefix, math_float_suffix);
6583 init_value = create_const_float(g, scalar_type, NAN);
6584 }
6585 } else zig_unreachable();
6586 } break;
6587 case ReduceOp_max: {
6588 if (scalar_type->id == ZigTypeIdInt) {
6589 const bool is_signed = scalar_type->data.integral.is_signed;
6590 return ZigLLVMBuildIntMaxReduce(g->builder, value, is_signed);
6591 } else if (scalar_type->id == ZigTypeIdFloat) {
6592 if (float_intrinsics_allowed) {
6593 return ZigLLVMBuildFPMaxReduce(g->builder, value);
6594 } else {
6595 snprintf(fn_name, sizeof(fn_name), "%sfmax%s", math_float_prefix, math_float_suffix);
6596 init_value = create_const_float(g, scalar_type, NAN);
6597 }
6598 } else zig_unreachable();
6599 } break;
6600 case ReduceOp_add: {
6601 if (scalar_type->id == ZigTypeIdInt) {
6602 return ZigLLVMBuildAddReduce(g->builder, value);
6603 } else if (scalar_type->id == ZigTypeIdFloat) {
6604 if (float_intrinsics_allowed) {
6605 LLVMValueRef neutral_value = LLVMConstReal(
6606 get_llvm_type(g, scalar_type), -0.0);
6607 return ZigLLVMBuildFPAddReduce(g->builder, neutral_value, value);
6608 } else {
6609 snprintf(fn_name, sizeof(fn_name), "__add%sf3", compiler_rt_type_abbrev);
6610 init_value = create_const_float(g, scalar_type, 0.0);
6611 }
6612 } else zig_unreachable();
6613 } break;
6614 case ReduceOp_mul: {
6615 if (scalar_type->id == ZigTypeIdInt) {
6616 return ZigLLVMBuildMulReduce(g->builder, value);
6617 } else if (scalar_type->id == ZigTypeIdFloat) {
6618 if (float_intrinsics_allowed) {
6619 LLVMValueRef neutral_value = LLVMConstReal(
6620 get_llvm_type(g, scalar_type), 1.0);
6621 return ZigLLVMBuildFPMulReduce(g->builder, neutral_value, value);
6622 } else {
6623 snprintf(fn_name, sizeof(fn_name), "__mul%sf3", compiler_rt_type_abbrev);
6624 init_value = create_const_float(g, scalar_type, 1.0);
6625 }
6626 } else zig_unreachable();
6627 } break;
6628 default:
6629 zig_unreachable();
6630 }
6631
6632
6633 LLVMValueRef llvm_init_value = gen_const_val(g, init_value, "");
6634 uint32_t vector_len = value_type->data.vector.len;
6635 LLVMTypeRef llvm_scalar_type = get_llvm_type(g, scalar_type);
6636 const LLVMValueRef llvm_fn = get_soft_float_fn(g, fn_name, 2, llvm_scalar_type, llvm_scalar_type);
6637 return ir_render_reduced_call(g, llvm_fn, value, vector_len, llvm_init_value, scalar_type);
6638}
6639
6640static LLVMValueRef ir_render_fence(CodeGen *g, Stage1Air *executable, Stage1AirInstFence *instruction) {
6641 LLVMAtomicOrdering atomic_order = to_LLVMAtomicOrdering(instruction->order);
6642 LLVMBuildFence(g->builder, atomic_order, false, "");
6643 return nullptr;
6644}
6645
6646static LLVMValueRef ir_render_truncate(CodeGen *g, Stage1Air *executable, Stage1AirInstTruncate *instruction) {
6647 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
6648 ZigType *dest_type = instruction->base.value->type;
6649 ZigType *src_type = instruction->target->value->type;
6650 if (dest_type == src_type) {
6651 // no-op
6652 return target_val;
6653 } if (src_type->data.integral.bit_count == dest_type->data.integral.bit_count) {
6654 return LLVMBuildBitCast(g->builder, target_val, get_llvm_type(g, dest_type), "");
6655 } else {
6656 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
6657 return LLVMBuildTrunc(g->builder, target_val, get_llvm_type(g, dest_type), "");
6658 }
6659}
6660
6661static LLVMValueRef ir_render_memset(CodeGen *g, Stage1Air *executable, Stage1AirInstMemset *instruction) {
6662 LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr);
6663 LLVMValueRef len_val = ir_llvm_value(g, instruction->count);
6664
6665 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
6666 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
6667
6668 ZigType *ptr_type = instruction->dest_ptr->value->type;
6669 assert(ptr_type->id == ZigTypeIdPointer);
6670
6671 bool val_is_undef = value_is_all_undef(g, instruction->byte->value);
6672 LLVMValueRef fill_char;
6673 if (val_is_undef) {
6674 if (ir_want_runtime_safety_scope(g, instruction->base.scope)) {
6675 fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
6676 } else {
6677 return nullptr;
6678 }
6679 } else {
6680 fill_char = ir_llvm_value(g, instruction->byte);
6681 }
6682 ZigLLVMBuildMemSet(g->builder, dest_ptr_casted, fill_char, len_val, get_ptr_align(g, ptr_type),
6683 ptr_type->data.pointer.is_volatile);
6684
6685 if (val_is_undef && g->valgrind_enabled) {
6686 gen_valgrind_undef(g, dest_ptr_casted, len_val);
6687 }
6688 return nullptr;
6689}
6690
6691static LLVMValueRef ir_render_memcpy(CodeGen *g, Stage1Air *executable, Stage1AirInstMemcpy *instruction) {
6692 LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr);
6693 LLVMValueRef src_ptr = ir_llvm_value(g, instruction->src_ptr);
6694 LLVMValueRef len_val = ir_llvm_value(g, instruction->count);
6695
6696 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
6697
6698 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
6699 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, ptr_u8, "");
6700
6701 ZigType *dest_ptr_type = instruction->dest_ptr->value->type;
6702 ZigType *src_ptr_type = instruction->src_ptr->value->type;
6703
6704 assert(dest_ptr_type->id == ZigTypeIdPointer);
6705 assert(src_ptr_type->id == ZigTypeIdPointer);
6706
6707 bool is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile);
6708 ZigLLVMBuildMemCpy(g->builder, dest_ptr_casted, get_ptr_align(g, dest_ptr_type),
6709 src_ptr_casted, get_ptr_align(g, src_ptr_type), len_val, is_volatile);
6710 return nullptr;
6711}
6712
6713static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, Stage1Air *executable, Stage1AirInstWasmMemorySize *instruction) {
6714 // TODO adjust for wasm64
6715 LLVMValueRef param = ir_llvm_value(g, instruction->index);
6716 LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(gen_wasm_memory_size(g)), gen_wasm_memory_size(g), &param, 1, "");
6717 return val;
6718}
6719
6720static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, Stage1Air *executable, Stage1AirInstWasmMemoryGrow *instruction) {
6721 // TODO adjust for wasm64
6722 LLVMValueRef params[] = {
6723 ir_llvm_value(g, instruction->index),
6724 ir_llvm_value(g, instruction->delta),
6725 };
6726 LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(gen_wasm_memory_grow(g)), gen_wasm_memory_grow(g), params, 2, "");
6727 return val;
6728}
6729
6730static LLVMValueRef ir_render_prefetch(CodeGen *g, Stage1Air *executable, Stage1AirInstPrefetch *instruction) {
6731 static_assert(PrefetchRwRead == 0, "");
6732 static_assert(PrefetchRwWrite == 1, "");
6733 assert(instruction->rw == PrefetchRwRead || instruction->rw == PrefetchRwWrite);
6734
6735 assert(instruction->locality >= 0 && instruction->locality <= 3);
6736
6737 static_assert(PrefetchCacheInstruction == 0, "");
6738 static_assert(PrefetchCacheData == 1, "");
6739 assert(instruction->cache == PrefetchCacheData || instruction->cache == PrefetchCacheInstruction);
6740
6741 // LLVM fails during codegen of instruction cache prefetchs for these architectures.
6742 // This is an LLVM bug as the prefetch intrinsic should be a noop if not supported by the target.
6743 // To work around this, simply don't emit llvm.prefetch in this case.
6744 // See https://bugs.llvm.org/show_bug.cgi?id=21037
6745 if (instruction->cache == PrefetchCacheInstruction) {
6746 switch (g->zig_target->arch) {
6747 case ZigLLVM_x86:
6748 case ZigLLVM_x86_64:
6749 case ZigLLVM_ppc:
6750 case ZigLLVM_ppcle:
6751 case ZigLLVM_ppc64:
6752 case ZigLLVM_ppc64le:
6753 return nullptr;
6754 default:
6755 break;
6756 }
6757 }
6758
6759 // Another case of the same LLVM bug described above
6760 if (instruction->rw == PrefetchRwWrite && instruction->cache == PrefetchCacheInstruction) {
6761 switch (g->zig_target->arch) {
6762 case ZigLLVM_arm:
6763 return nullptr;
6764 default:
6765 break;
6766 }
6767
6768 }
6769
6770 LLVMValueRef params[] = {
6771 LLVMBuildBitCast(g->builder, ir_llvm_value(g, instruction->ptr), LLVMPointerType(LLVMInt8Type(), 0), ""),
6772 LLVMConstInt(LLVMInt32Type(), instruction->rw, false),
6773 LLVMConstInt(LLVMInt32Type(), instruction->locality, false),
6774 LLVMConstInt(LLVMInt32Type(), instruction->cache, false),
6775 };
6776 LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(gen_prefetch(g)), gen_prefetch(g), params, 4, "");
6777 return val;
6778}
6779
6780static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1AirInstSlice *instruction) {
6781 Error err;
6782
6783 LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr);
6784 ZigType *array_ptr_type = instruction->ptr->value->type;
6785 assert(array_ptr_type->id == ZigTypeIdPointer);
6786 ZigType *array_type = array_ptr_type->data.pointer.child_type;
6787 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
6788
6789 bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
6790
6791 // The result is either a slice or a pointer to an array
6792 ZigType *result_type = instruction->base.value->type;
6793
6794 // This is not whether the result type has a sentinel, but whether there should be a sentinel check,
6795 // e.g. if they used [a..b :s] syntax.
6796 ZigValue *sentinel = instruction->sentinel;
6797
6798 LLVMValueRef slice_start_ptr = nullptr;
6799 LLVMValueRef len_value = nullptr;
6800
6801 if (array_type->id == ZigTypeIdArray ||
6802 (array_type->id == ZigTypeIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
6803 {
6804 if (array_type->id == ZigTypeIdPointer) {
6805 array_type = array_type->data.pointer.child_type;
6806 }
6807 LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
6808 LLVMValueRef end_val;
6809 if (instruction->end) {
6810 end_val = ir_llvm_value(g, instruction->end);
6811 } else {
6812 end_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, array_type->data.array.len, false);
6813 }
6814
6815 if (want_runtime_safety) {
6816 // Safety check: start <= end
6817 if (instruction->start->value->special == ConstValSpecialRuntime || instruction->end) {
6818 add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
6819 }
6820
6821 // Safety check: the last element of the slice (the sentinel if
6822 // requested) must be inside the array
6823 // XXX: Overflow is not checked here...
6824 const size_t full_len = array_type->data.array.len +
6825 (array_type->data.array.sentinel != nullptr);
6826 LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
6827 full_len, false);
6828
6829 LLVMValueRef check_end_val = end_val;
6830 if (sentinel != nullptr) {
6831 LLVMValueRef usize_one = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 1, false);
6832 check_end_val = LLVMBuildNUWAdd(g->builder, end_val, usize_one, "");
6833 }
6834 add_bounds_check(g, check_end_val, LLVMIntEQ, nullptr, LLVMIntULE, array_end);
6835 }
6836
6837 bool value_has_bits;
6838 if ((err = type_has_bits2(g, array_type, &value_has_bits)))
6839 codegen_report_errors_and_exit(g);
6840
6841 if (value_has_bits) {
6842 LLVMTypeRef array_llvm_ty = get_llvm_type(g, array_type);
6843 if (want_runtime_safety && sentinel != nullptr) {
6844 LLVMValueRef indices[] = {
6845 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
6846 end_val,
6847 };
6848 LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder,
6849 array_llvm_ty, array_ptr, indices, 2, "");
6850 add_sentinel_check(g, sentinel_elem_ptr, sentinel);
6851 }
6852
6853 LLVMValueRef indices[] = {
6854 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
6855 start_val,
6856 };
6857 slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, array_llvm_ty, array_ptr, indices, 2, "");
6858 }
6859
6860 len_value = LLVMBuildNUWSub(g->builder, end_val, start_val, "");
6861 } else if (array_type->id == ZigTypeIdPointer) {
6862 assert(array_type->data.pointer.ptr_len != PtrLenSingle);
6863 LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
6864 LLVMValueRef end_val = ir_llvm_value(g, instruction->end);
6865
6866 if (want_runtime_safety) {
6867 // Safety check: start <= end
6868 add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
6869 }
6870
6871 bool value_has_bits;
6872 if ((err = type_has_bits2(g, array_type, &value_has_bits)))
6873 codegen_report_errors_and_exit(g);
6874
6875 if (value_has_bits) {
6876 LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.pointer.child_type);
6877 if (want_runtime_safety && sentinel != nullptr) {
6878 LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty,
6879 array_ptr, &end_val, 1, "");
6880 add_sentinel_check(g, sentinel_elem_ptr, sentinel);
6881 }
6882
6883 slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, array_ptr,
6884 &start_val, 1, "");
6885 }
6886
6887 len_value = LLVMBuildNUWSub(g->builder, end_val, start_val, "");
6888 } else if (array_type->id == ZigTypeIdStruct) {
6889 assert(array_type->data.structure.special == StructSpecialSlice);
6890 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
6891
6892 const size_t gen_len_index = array_type->data.structure.fields[slice_len_index]->gen_index;
6893 assert(gen_len_index != SIZE_MAX);
6894
6895 LLVMValueRef prev_end = nullptr;
6896 if (!instruction->end || want_runtime_safety) {
6897 LLVMValueRef src_len_ptr = LLVMBuildStructGEP2(g->builder,
6898 get_llvm_type(g, array_type), array_ptr, gen_len_index, "");
6899 prev_end = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(src_len_ptr), src_len_ptr, 0, false, "");
6900 }
6901
6902 LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
6903 LLVMValueRef end_val;
6904 if (instruction->end) {
6905 end_val = ir_llvm_value(g, instruction->end);
6906 } else {
6907 end_val = prev_end;
6908 }
6909
6910 ZigType *ptr_field_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
6911
6912 if (want_runtime_safety) {
6913 assert(prev_end);
6914 // Safety check: start <= end
6915 add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
6916
6917 // Safety check: the sentinel counts as one more element
6918 // XXX: Overflow is not checked here...
6919 LLVMValueRef check_prev_end = prev_end;
6920 if (ptr_field_type->data.pointer.sentinel != nullptr) {
6921 LLVMValueRef usize_one = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 1, false);
6922 check_prev_end = LLVMBuildNUWAdd(g->builder, prev_end, usize_one, "");
6923 }
6924 LLVMValueRef check_end_val = end_val;
6925 if (sentinel != nullptr) {
6926 LLVMValueRef usize_one = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 1, false);
6927 check_end_val = LLVMBuildNUWAdd(g->builder, end_val, usize_one, "");
6928 }
6929
6930 add_bounds_check(g, check_end_val, LLVMIntEQ, nullptr, LLVMIntULE, check_prev_end);
6931 }
6932
6933 bool ptr_has_bits;
6934 if ((err = type_has_bits2(g, ptr_field_type, &ptr_has_bits)))
6935 codegen_report_errors_and_exit(g);
6936
6937 if (ptr_has_bits) {
6938 LLVMTypeRef elem_llvm_ty = get_llvm_type(g, ptr_field_type->data.pointer.child_type);
6939 const size_t gen_ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index;
6940 assert(gen_ptr_index != SIZE_MAX);
6941
6942 LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP2(g->builder,
6943 get_llvm_type(g, array_type), array_ptr, gen_ptr_index, "");
6944 LLVMValueRef src_ptr = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(src_ptr_ptr),
6945 src_ptr_ptr, 0, false, "");
6946
6947 if (sentinel != nullptr) {
6948 LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty,
6949 src_ptr, &end_val, 1, "");
6950 add_sentinel_check(g, sentinel_elem_ptr, sentinel);
6951 }
6952
6953 slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, src_ptr, &start_val, 1, "");
6954 }
6955
6956 len_value = LLVMBuildNUWSub(g->builder, end_val, start_val, "");
6957 } else {
6958 zig_unreachable();
6959 }
6960
6961 bool result_has_bits;
6962 if ((err = type_has_bits2(g, result_type, &result_has_bits)))
6963 codegen_report_errors_and_exit(g);
6964
6965 // Nothing to do, we're only interested in the bound checks emitted above
6966 if (!result_has_bits)
6967 return nullptr;
6968
6969 // The starting pointer for the slice may be null in case of zero-sized
6970 // arrays, the length value is always defined.
6971 assert(len_value != nullptr);
6972
6973 // The slice decays into a pointer to an array, the size is tracked in the
6974 // type itself
6975 if (result_type->id == ZigTypeIdPointer) {
6976 ir_assert(instruction->result_loc == nullptr, &instruction->base);
6977 LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type);
6978
6979 if (slice_start_ptr != nullptr) {
6980 return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
6981 }
6982
6983 return LLVMGetUndef(result_ptr_type);
6984 }
6985
6986 ir_assert(instruction->result_loc != nullptr, &instruction->base);
6987 // Create a new slice
6988 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
6989
6990 ZigType *slice_ptr_type = result_type->data.structure.fields[slice_ptr_index]->type_entry;
6991
6992 // The slice may not have a pointer at all if it points to a zero-sized type
6993 const size_t gen_ptr_index = result_type->data.structure.fields[slice_ptr_index]->gen_index;
6994 if (gen_ptr_index != SIZE_MAX) {
6995 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder,
6996 get_llvm_type(g, result_type), tmp_struct_ptr, gen_ptr_index, "");
6997 if (slice_start_ptr != nullptr) {
6998 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
6999 } else if (want_runtime_safety) {
7000 gen_undef_init(g, slice_ptr_type, slice_ptr_type, ptr_field_ptr);
7001 } else {
7002 gen_store_untyped(g, LLVMGetUndef(get_llvm_type(g, slice_ptr_type)), ptr_field_ptr, 0, false);
7003 }
7004 }
7005
7006 const size_t gen_len_index = result_type->data.structure.fields[slice_len_index]->gen_index;
7007 assert(gen_len_index != SIZE_MAX);
7008
7009 LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder,
7010 get_llvm_type(g, result_type), tmp_struct_ptr, gen_len_index, "");
7011 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
7012
7013 return tmp_struct_ptr;
7014}
7015
7016static LLVMValueRef get_trap_fn_val(CodeGen *g) {
7017 if (g->trap_fn_val)
7018 return g->trap_fn_val;
7019
7020 LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), nullptr, 0, false);
7021 g->trap_fn_val = LLVMAddFunction(g->module, "llvm.debugtrap", fn_type);
7022 assert(LLVMGetIntrinsicID(g->trap_fn_val));
7023
7024 return g->trap_fn_val;
7025}
7026
7027
7028static LLVMValueRef ir_render_breakpoint(CodeGen *g, Stage1Air *executable, Stage1AirInstBreakpoint *instruction) {
7029 LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(get_trap_fn_val(g)), get_trap_fn_val(g), nullptr, 0, "");
7030 return nullptr;
7031}
7032
7033static LLVMValueRef ir_render_return_address(CodeGen *g, Stage1Air *executable,
7034 Stage1AirInstReturnAddress *instruction)
7035{
7036 if ((target_is_wasm(g->zig_target) && g->zig_target->os != OsEmscripten) || target_is_bpf(g->zig_target)) {
7037 // LLVM 13 reports "Non-Emscripten WebAssembly hasn't implemented __builtin_return_address"
7038 // https://github.com/ziglang/zig/issues/11946
7039 return LLVMConstNull(get_llvm_type(g, instruction->base.value->type));
7040 }
7041
7042 LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type);
7043 LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, "");
7044 return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, "");
7045}
7046
7047static LLVMValueRef get_frame_address_fn_val(CodeGen *g) {
7048 if (g->frame_address_fn_val)
7049 return g->frame_address_fn_val;
7050
7051 ZigType *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
7052
7053 LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, return_type),
7054 &g->builtin_types.entry_i32->llvm_type, 1, false);
7055 g->frame_address_fn_val = LLVMAddFunction(g->module, "llvm.frameaddress.p0", fn_type);
7056 assert(LLVMGetIntrinsicID(g->frame_address_fn_val));
7057
7058 return g->frame_address_fn_val;
7059}
7060
7061static LLVMValueRef ir_render_frame_address(CodeGen *g, Stage1Air *executable,
7062 Stage1AirInstFrameAddress *instruction)
7063{
7064 LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type);
7065 LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(get_frame_address_fn_val(g)), get_frame_address_fn_val(g), &zero, 1, "");
7066 return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, "");
7067}
7068
7069static LLVMValueRef ir_render_handle(CodeGen *g, Stage1Air *executable, Stage1AirInstFrameHandle *instruction) {
7070 return g->cur_frame_ptr;
7071}
7072
7073static LLVMValueRef render_shl_with_overflow(CodeGen *g, Stage1AirInstOverflowOp *instruction) {
7074 ZigType *int_type = instruction->result_ptr_type;
7075 assert(int_type->id == ZigTypeIdInt);
7076
7077 LLVMValueRef op1 = ir_llvm_value(g, instruction->op1);
7078 LLVMValueRef op2 = ir_llvm_value(g, instruction->op2);
7079 LLVMValueRef ptr_result = ir_llvm_value(g, instruction->result_ptr);
7080
7081 LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, instruction->op2->value->type,
7082 instruction->op1->value->type, op2);
7083
7084 LLVMValueRef result = LLVMBuildShl(g->builder, op1, op2_casted, "");
7085 LLVMValueRef orig_val;
7086 if (int_type->data.integral.is_signed) {
7087 orig_val = LLVMBuildAShr(g->builder, result, op2_casted, "");
7088 } else {
7089 orig_val = LLVMBuildLShr(g->builder, result, op2_casted, "");
7090 }
7091 LLVMValueRef overflow_bit = LLVMBuildICmp(g->builder, LLVMIntNE, op1, orig_val, "");
7092
7093 gen_store(g, result, ptr_result, instruction->result_ptr->value->type);
7094
7095 return overflow_bit;
7096}
7097
7098static LLVMValueRef ir_render_overflow_op(CodeGen *g, Stage1Air *executable, Stage1AirInstOverflowOp *instruction) {
7099 AddSubMul add_sub_mul;
7100 switch (instruction->op) {
7101 case IrOverflowOpAdd:
7102 add_sub_mul = AddSubMulAdd;
7103 break;
7104 case IrOverflowOpSub:
7105 add_sub_mul = AddSubMulSub;
7106 break;
7107 case IrOverflowOpMul:
7108 add_sub_mul = AddSubMulMul;
7109 break;
7110 case IrOverflowOpShl:
7111 return render_shl_with_overflow(g, instruction);
7112 }
7113
7114 ZigType *int_type = instruction->result_ptr_type;
7115 assert(int_type->id == ZigTypeIdInt);
7116
7117 LLVMValueRef fn_val = get_int_overflow_fn(g, int_type, add_sub_mul);
7118
7119 LLVMValueRef op1 = ir_llvm_value(g, instruction->op1);
7120 LLVMValueRef op2 = ir_llvm_value(g, instruction->op2);
7121 LLVMValueRef ptr_result = ir_llvm_value(g, instruction->result_ptr);
7122
7123 LLVMValueRef params[] = {
7124 op1,
7125 op2,
7126 };
7127
7128 LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, "");
7129 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
7130 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
7131 gen_store(g, result, ptr_result, instruction->result_ptr->value->type);
7132
7133 return overflow_bit;
7134}
7135
7136static LLVMValueRef ir_render_test_err(CodeGen *g, Stage1Air *executable, Stage1AirInstTestErr *instruction) {
7137 ZigType *err_union_type = instruction->err_union->value->type;
7138 ZigType *payload_type = err_union_type->data.error_union.payload_type;
7139 LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->err_union);
7140
7141 LLVMValueRef err_val;
7142 if (type_has_bits(g, payload_type)) {
7143 LLVMValueRef err_val_ptr = LLVMBuildStructGEP2(g->builder,
7144 get_llvm_type(g, err_union_type), err_union_handle, err_union_err_index, "");
7145 err_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(err_val_ptr), err_val_ptr, 0, false, "");
7146 } else {
7147 err_val = err_union_handle;
7148 }
7149
7150 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, g->err_tag_type));
7151 return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");
7152}
7153
7154static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, Stage1Air *executable,
7155 Stage1AirInstUnwrapErrCode *instruction)
7156{
7157 if (instruction->base.value->special != ConstValSpecialRuntime)
7158 return nullptr;
7159
7160 ZigType *ptr_type = instruction->err_union_ptr->value->type;
7161 assert(ptr_type->id == ZigTypeIdPointer);
7162 ZigType *err_union_type = ptr_type->data.pointer.child_type;
7163 ZigType *payload_type = err_union_type->data.error_union.payload_type;
7164 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union_ptr);
7165 if (!type_has_bits(g, payload_type)) {
7166 return err_union_ptr;
7167 } else {
7168 // TODO assign undef to the payload
7169 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
7170 return LLVMBuildStructGEP2(g->builder, get_llvm_type(g, err_union_type), err_union_handle,
7171 err_union_err_index, "");
7172 }
7173}
7174
7175static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, Stage1Air *executable,
7176 Stage1AirInstUnwrapErrPayload *instruction)
7177{
7178 Error err;
7179
7180 if (instruction->base.value->special != ConstValSpecialRuntime)
7181 return nullptr;
7182
7183 bool want_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base) &&
7184 g->errors_by_index.length > 1;
7185
7186 ZigType *ptr_type = instruction->value->value->type;
7187 assert(ptr_type->id == ZigTypeIdPointer);
7188 ZigType *err_union_type = ptr_type->data.pointer.child_type;
7189 ZigType *payload_type = err_union_type->data.error_union.payload_type;
7190 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
7191
7192 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, g->err_tag_type));
7193 bool value_has_bits;
7194 if ((err = type_has_bits2(g, instruction->base.value->type, &value_has_bits)))
7195 codegen_report_errors_and_exit(g);
7196 if (!want_safety && !value_has_bits) {
7197 if (instruction->initializing) {
7198 gen_store_untyped(g, zero, err_union_ptr, 0, false);
7199 }
7200 return nullptr;
7201 }
7202
7203
7204 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
7205
7206 if (!type_has_bits(g, err_union_type->data.error_union.err_set_type)) {
7207 return err_union_handle;
7208 }
7209
7210 LLVMTypeRef err_union_llvm_ty = get_llvm_type(g, err_union_type);
7211
7212 if (want_safety) {
7213 LLVMValueRef err_val;
7214 if (type_has_bits(g, payload_type)) {
7215 LLVMValueRef err_val_ptr = LLVMBuildStructGEP2(g->builder, err_union_llvm_ty,
7216 err_union_handle, err_union_err_index, "");
7217 err_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(err_val_ptr), err_val_ptr, 0, false, "");
7218 } else {
7219 err_val = err_union_handle;
7220 }
7221 LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
7222 LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrError");
7223 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrOk");
7224 LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
7225
7226 LLVMPositionBuilderAtEnd(g->builder, err_block);
7227 gen_safety_crash_for_err(g, err_val, instruction->base.scope);
7228
7229 LLVMPositionBuilderAtEnd(g->builder, ok_block);
7230 }
7231
7232 if (type_has_bits(g, payload_type)) {
7233 if (instruction->initializing) {
7234 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP2(g->builder, err_union_llvm_ty,
7235 err_union_handle, err_union_err_index, "");
7236 LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type));
7237 gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false);
7238 }
7239 return LLVMBuildStructGEP2(g->builder, err_union_llvm_ty, err_union_handle,
7240 err_union_payload_index, "");
7241 } else {
7242 if (instruction->initializing) {
7243 gen_store_untyped(g, zero, err_union_ptr, 0, false);
7244 }
7245 return nullptr;
7246 }
7247}
7248
7249static LLVMValueRef ir_render_optional_wrap(CodeGen *g, Stage1Air *executable, Stage1AirInstOptionalWrap *instruction) {
7250 ZigType *wanted_type = instruction->base.value->type;
7251
7252 assert(wanted_type->id == ZigTypeIdOptional);
7253
7254 ZigType *child_type = wanted_type->data.maybe.child_type;
7255
7256 if (!type_has_bits(g, child_type)) {
7257 LLVMValueRef result = LLVMConstAllOnes(LLVMInt1Type());
7258 if (instruction->result_loc != nullptr) {
7259 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
7260 gen_store_untyped(g, result, result_loc, 0, false);
7261 }
7262 return result;
7263 }
7264
7265 LLVMValueRef payload_val = ir_llvm_value(g, instruction->operand);
7266 if (!handle_is_ptr(g, wanted_type)) {
7267 if (instruction->result_loc != nullptr) {
7268 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
7269 gen_store_untyped(g, payload_val, result_loc, 0, false);
7270 }
7271 return payload_val;
7272 }
7273
7274 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
7275 LLVMTypeRef result_llvm_struct_ty = get_llvm_type(g, wanted_type);
7276
7277 LLVMValueRef val_ptr = LLVMBuildStructGEP2(g->builder, result_llvm_struct_ty, result_loc,
7278 maybe_child_index, "");
7279 // child_type and instruction->value->value->type may differ by constness
7280 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
7281 LLVMValueRef maybe_ptr = LLVMBuildStructGEP2(g->builder, result_llvm_struct_ty, result_loc,
7282 maybe_null_index, "");
7283 gen_store_untyped(g, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr, 0, false);
7284
7285 return result_loc;
7286}
7287
7288static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, Stage1Air *executable, Stage1AirInstErrWrapCode *instruction) {
7289 ZigType *wanted_type = instruction->base.value->type;
7290
7291 assert(wanted_type->id == ZigTypeIdErrorUnion);
7292
7293 LLVMValueRef err_val = ir_llvm_value(g, instruction->operand);
7294
7295 if (!handle_is_ptr(g, wanted_type))
7296 return err_val;
7297
7298 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
7299
7300 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, wanted_type),
7301 result_loc, err_union_err_index, "");
7302 gen_store_untyped(g, err_val, err_tag_ptr, 0, false);
7303
7304 // TODO store undef to the payload
7305
7306 return result_loc;
7307}
7308
7309static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, Stage1Air *executable, Stage1AirInstErrWrapPayload *instruction) {
7310 ZigType *wanted_type = instruction->base.value->type;
7311
7312 assert(wanted_type->id == ZigTypeIdErrorUnion);
7313
7314 ZigType *payload_type = wanted_type->data.error_union.payload_type;
7315 ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
7316
7317 if (!type_has_bits(g, err_set_type)) {
7318 return ir_llvm_value(g, instruction->operand);
7319 }
7320
7321 LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type));
7322
7323 if (!type_has_bits(g, payload_type))
7324 return ok_err_val;
7325
7326
7327 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
7328
7329 LLVMValueRef payload_val = ir_llvm_value(g, instruction->operand);
7330 LLVMTypeRef result_struct_llvm_ty = get_llvm_type(g, wanted_type);
7331
7332 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP2(g->builder, result_struct_llvm_ty, result_loc,
7333 err_union_err_index, "");
7334 gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false);
7335
7336 LLVMValueRef payload_ptr = LLVMBuildStructGEP2(g->builder, result_struct_llvm_ty, result_loc,
7337 err_union_payload_index, "");
7338 gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, payload_type, false), payload_val);
7339
7340 return result_loc;
7341}
7342
7343static LLVMValueRef ir_render_union_tag(CodeGen *g, Stage1Air *executable, Stage1AirInstUnionTag *instruction) {
7344 ZigType *union_type = instruction->value->value->type;
7345
7346 ZigType *tag_type = union_type->data.unionation.tag_type;
7347 if (!type_has_bits(g, tag_type))
7348 return nullptr;
7349
7350 LLVMValueRef union_val = ir_llvm_value(g, instruction->value);
7351 if (union_type->data.unionation.gen_field_count == 0)
7352 return union_val;
7353
7354 assert(union_type->data.unionation.gen_tag_index != SIZE_MAX);
7355 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP2(g->builder,
7356 get_llvm_type(g, union_type), union_val,
7357 union_type->data.unionation.gen_tag_index, "");
7358 ZigType *ptr_type = get_pointer_to_type(g, tag_type, false);
7359 return get_handle_value(g, tag_field_ptr, tag_type, ptr_type);
7360}
7361
7362static LLVMValueRef ir_render_panic(CodeGen *g, Stage1Air *executable, Stage1AirInstPanic *instruction) {
7363 bool is_llvm_alloca;
7364 LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca);
7365 gen_panic(g, ir_llvm_value(g, instruction->msg), err_ret_trace_val, is_llvm_alloca);
7366 return nullptr;
7367}
7368
7369static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, Stage1Air *executable,
7370 Stage1AirInstAtomicRmw *instruction)
7371{
7372 bool is_signed;
7373 ZigType *operand_type = instruction->operand->value->type;
7374 bool is_float = operand_type->id == ZigTypeIdFloat;
7375 if (operand_type->id == ZigTypeIdInt) {
7376 is_signed = operand_type->data.integral.is_signed;
7377 } else {
7378 is_signed = false;
7379 }
7380 LLVMAtomicRMWBinOp op = to_LLVMAtomicRMWBinOp(instruction->op, is_signed, is_float);
7381 LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering);
7382 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
7383 LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
7384
7385 LLVMTypeRef actual_abi_type = get_atomic_abi_type(g, instruction->ptr,
7386 op == LLVMAtomicRMWBinOpXchg);
7387 if (actual_abi_type != nullptr) {
7388 // operand needs widening and truncating or bitcasting.
7389 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,
7390 LLVMPointerType(actual_abi_type, 0), "");
7391 LLVMValueRef casted_operand;
7392 if (is_float) {
7393 casted_operand = LLVMBuildBitCast(g->builder, operand, actual_abi_type, "");
7394 } else if (operand_type->data.integral.is_signed) {
7395 casted_operand = LLVMBuildSExt(g->builder, operand, actual_abi_type, "");
7396 } else {
7397 casted_operand = LLVMBuildZExt(g->builder, operand, actual_abi_type, "");
7398 }
7399 LLVMValueRef uncasted_result = LLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering,
7400 g->is_single_threaded);
7401 if (is_float) {
7402 return LLVMBuildBitCast(g->builder, uncasted_result, get_llvm_type(g, operand_type), "");
7403 } else {
7404 return LLVMBuildTrunc(g->builder, uncasted_result, get_llvm_type(g, operand_type), "");
7405 }
7406 }
7407
7408 if (get_codegen_ptr_type_bail(g, operand_type) == nullptr) {
7409 return LLVMBuildAtomicRMW(g->builder, op, ptr, operand, ordering, g->is_single_threaded);
7410 }
7411
7412 // it's a pointer but we need to treat it as an int
7413 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,
7414 LLVMPointerType(g->builtin_types.entry_usize->llvm_type, 0), "");
7415 LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, g->builtin_types.entry_usize->llvm_type, "");
7416 LLVMValueRef uncasted_result = LLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering,
7417 g->is_single_threaded);
7418 return LLVMBuildIntToPtr(g->builder, uncasted_result, get_llvm_type(g, operand_type), "");
7419}
7420
7421static LLVMValueRef ir_render_atomic_load(CodeGen *g, Stage1Air *executable,
7422 Stage1AirInstAtomicLoad *instruction)
7423{
7424 LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering);
7425 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
7426
7427 ZigType *operand_type = instruction->ptr->value->type->data.pointer.child_type;
7428 LLVMTypeRef actual_abi_type = get_atomic_abi_type(g, instruction->ptr, false);
7429 if (actual_abi_type != nullptr) {
7430 // operand needs widening and truncating
7431 ptr = LLVMBuildBitCast(g->builder, ptr, LLVMPointerType(actual_abi_type, 0), "");
7432 LLVMValueRef load_inst = gen_load_untyped(g, actual_abi_type, ptr,
7433 get_ptr_align(g, instruction->ptr->value->type),
7434 instruction->ptr->value->type->data.pointer.is_volatile, "");
7435 LLVMSetOrdering(load_inst, ordering);
7436 return LLVMBuildTrunc(g->builder, load_inst, get_llvm_type(g, operand_type), "");
7437 }
7438 LLVMValueRef load_inst = gen_load(g, ptr, instruction->ptr->value->type, "");
7439 LLVMSetOrdering(load_inst, ordering);
7440 return load_inst;
7441}
7442
7443static LLVMValueRef ir_render_atomic_store(CodeGen *g, Stage1Air *executable,
7444 Stage1AirInstAtomicStore *instruction)
7445{
7446 LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering);
7447 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
7448 LLVMValueRef value = ir_llvm_value(g, instruction->value);
7449
7450 LLVMTypeRef actual_abi_type = get_atomic_abi_type(g, instruction->ptr, false);
7451 if (actual_abi_type != nullptr) {
7452 // operand needs widening
7453 ptr = LLVMBuildBitCast(g->builder, ptr,
7454 LLVMPointerType(actual_abi_type, 0), "");
7455 if (instruction->value->value->type->data.integral.is_signed) {
7456 value = LLVMBuildSExt(g->builder, value, actual_abi_type, "");
7457 } else {
7458 value = LLVMBuildZExt(g->builder, value, actual_abi_type, "");
7459 }
7460 }
7461 LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value->type);
7462 LLVMSetOrdering(store_inst, ordering);
7463 return nullptr;
7464}
7465
7466static LLVMValueRef ir_render_float_op(CodeGen *g, Stage1Air *executable, Stage1AirInstFloatOp *instruction) {
7467 LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
7468 ZigType *operand_type = instruction->operand->value->type;
7469 return gen_float_un_op(g, operand, operand_type, instruction->fn_id);
7470}
7471
7472static LLVMValueRef ir_render_soft_mul_add(CodeGen *g, Stage1Air *executable, Stage1AirInstMulAdd *instruction, ZigType *float_type) {
7473 ZigType *operand_type = instruction->op1->value->type;
7474 uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0;
7475
7476 const char *fn_name;
7477 if (float_type == g->builtin_types.entry_f16)
7478 fn_name = "__fmah";
7479 else if (float_type == g->builtin_types.entry_f32)
7480 fn_name = "fmaf";
7481 else if (float_type == g->builtin_types.entry_f64)
7482 fn_name = "fma";
7483 else if (float_type == g->builtin_types.entry_f80)
7484 fn_name = "__fmax";
7485 else if (float_type == g->builtin_types.entry_f128)
7486 fn_name = "fmaq";
7487 else
7488 zig_unreachable();
7489
7490 LLVMTypeRef float_type_ref = float_type->llvm_type;
7491 LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, 3, float_type_ref, float_type_ref);
7492
7493 LLVMValueRef op1 = ir_llvm_value(g, instruction->op1);
7494 LLVMValueRef op2 = ir_llvm_value(g, instruction->op2);
7495 LLVMValueRef op3 = ir_llvm_value(g, instruction->op3);
7496 if (vector_len == 0) {
7497 LLVMValueRef params[3] = { op1, op2, op3 };
7498 return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, 3, "");
7499 }
7500
7501 LLVMValueRef result = LLVMGetUndef(get_llvm_type(g, instruction->op1->value->type));
7502 LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type;
7503 for (uint32_t i = 0; i < vector_len; i++) {
7504 LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false);
7505
7506 LLVMValueRef params[3] = {
7507 LLVMBuildExtractElement(g->builder, op1, index_value, ""),
7508 LLVMBuildExtractElement(g->builder, op2, index_value, ""),
7509 LLVMBuildExtractElement(g->builder, op3, index_value, ""),
7510 };
7511 LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, 3, "");
7512 result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, "");
7513 }
7514 return result;
7515}
7516
7517static LLVMValueRef ir_render_mul_add(CodeGen *g, Stage1Air *executable, Stage1AirInstMulAdd *instruction) {
7518 ZigType *operand_type = instruction->op1->value->type;
7519 operand_type = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.elem_type : operand_type;
7520 if ((operand_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) ||
7521 (operand_type == g->builtin_types.entry_f128 && !target_long_double_is_f128(g->zig_target)) ||
7522 (operand_type == g->builtin_types.entry_f16 && !target_is_arm(g->zig_target))) {
7523 return ir_render_soft_mul_add(g, executable, instruction, operand_type);
7524 }
7525 LLVMValueRef op1 = ir_llvm_value(g, instruction->op1);
7526 LLVMValueRef op2 = ir_llvm_value(g, instruction->op2);
7527 LLVMValueRef op3 = ir_llvm_value(g, instruction->op3);
7528 assert(instruction->base.value->type->id == ZigTypeIdFloat ||
7529 instruction->base.value->type->id == ZigTypeIdVector);
7530 LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFMA, BuiltinFnIdMulAdd);
7531 LLVMValueRef args[3] = { op1, op2, op3 };
7532 return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, args, 3, "");
7533}
7534
7535static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, Stage1AirInstBswap *instruction) {
7536 LLVMValueRef op = ir_llvm_value(g, instruction->op);
7537 ZigType *expr_type = instruction->base.value->type;
7538 bool is_vector = expr_type->id == ZigTypeIdVector;
7539 ZigType *int_type = is_vector ? expr_type->data.vector.elem_type : expr_type;
7540 assert(int_type->id == ZigTypeIdInt);
7541 if (int_type->data.integral.bit_count % 16 == 0) {
7542 LLVMValueRef fn_val = get_int_builtin_fn(g, expr_type, BuiltinFnIdBswap);
7543 return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &op, 1, "");
7544 }
7545 // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate
7546 ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed,
7547 int_type->data.integral.bit_count + 8);
7548 LLVMValueRef shift_amt = LLVMConstInt(get_llvm_type(g, extended_type), 8, false);
7549 if (is_vector) {
7550 extended_type = get_vector_type(g, expr_type->data.vector.len, extended_type);
7551 LLVMValueRef *values = heap::c_allocator.allocate_nonzero<LLVMValueRef>(expr_type->data.vector.len);
7552 for (uint32_t i = 0; i < expr_type->data.vector.len; i += 1) {
7553 values[i] = shift_amt;
7554 }
7555 shift_amt = LLVMConstVector(values, expr_type->data.vector.len);
7556 heap::c_allocator.deallocate(values, expr_type->data.vector.len);
7557 }
7558 // aabbcc
7559 LLVMValueRef extended = LLVMBuildZExt(g->builder, op, get_llvm_type(g, extended_type), "");
7560 // 00aabbcc
7561 LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap);
7562 LLVMValueRef swapped = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &extended, 1, "");
7563 // ccbbaa00
7564 LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, shift_amt, "");
7565 // 00ccbbaa
7566 return LLVMBuildTrunc(g->builder, shifted, get_llvm_type(g, expr_type), "");
7567}
7568
7569static LLVMValueRef ir_render_extern(CodeGen *g, Stage1Air *executable,
7570 Stage1AirInstExtern *instruction)
7571{
7572 ZigType *expr_type = instruction->base.value->type;
7573 assert(get_src_ptr_type(expr_type));
7574
7575 const char *symbol_name = buf_ptr(instruction->name);
7576 const LLVMLinkage linkage = to_llvm_linkage(instruction->linkage, true);
7577
7578 LLVMValueRef global_value = LLVMGetNamedGlobal(g->module, symbol_name);
7579 if (global_value == nullptr) {
7580 global_value = LLVMAddGlobal(g->module, get_llvm_type(g, expr_type), symbol_name);
7581 LLVMSetLinkage(global_value, linkage);
7582 LLVMSetGlobalConstant(global_value, true);
7583 if (instruction->is_thread_local)
7584 LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
7585 } else if (LLVMGetLinkage(global_value) != linkage) {
7586 // XXX: Handle this case better!
7587 zig_panic("duplicate extern symbol");
7588 }
7589
7590 return LLVMBuildBitCast(g->builder, global_value, get_llvm_type(g, expr_type), "");
7591}
7592
7593static LLVMValueRef ir_render_bit_reverse(CodeGen *g, Stage1Air *executable, Stage1AirInstBitReverse *instruction) {
7594 LLVMValueRef op = ir_llvm_value(g, instruction->op);
7595 ZigType *int_type = instruction->base.value->type;
7596 assert(int_type->id == ZigTypeIdInt);
7597 LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value->type, BuiltinFnIdBitReverse);
7598 return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &op, 1, "");
7599}
7600
7601static LLVMValueRef ir_render_vector_to_array(CodeGen *g, Stage1Air *executable,
7602 Stage1AirInstVectorToArray *instruction)
7603{
7604 ZigType *array_type = instruction->base.value->type;
7605 assert(array_type->id == ZigTypeIdArray);
7606 assert(handle_is_ptr(g, array_type));
7607 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
7608 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
7609
7610 ZigType *elem_type = array_type->data.array.child_type;
7611 bool bitcast_ok = elem_type->size_in_bits == elem_type->abi_size * 8;
7612 if (bitcast_ok) {
7613 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc,
7614 LLVMPointerType(get_llvm_type(g, instruction->vector->value->type), 0), "");
7615 uint32_t alignment = get_ptr_align(g, instruction->result_loc->value->type);
7616 gen_store_untyped(g, vector, casted_ptr, alignment, false);
7617 } else {
7618 // If the ABI size of the element type is not evenly divisible by size_in_bits, a simple bitcast
7619 // will not work, and we fall back to extractelement.
7620 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
7621 LLVMTypeRef u32_type_ref = LLVMInt32Type();
7622 LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false);
7623 LLVMTypeRef array_llvm_ty = get_llvm_type(g, array_type);
7624 for (uintptr_t i = 0; i < instruction->vector->value->type->data.vector.len; i++) {
7625 LLVMValueRef index_usize = LLVMConstInt(usize_type_ref, i, false);
7626 LLVMValueRef index_u32 = LLVMConstInt(u32_type_ref, i, false);
7627 LLVMValueRef indexes[] = { zero, index_usize };
7628 LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP2(g->builder, array_llvm_ty, result_loc, indexes, 2, "");
7629 LLVMValueRef elem = LLVMBuildExtractElement(g->builder, vector, index_u32, "");
7630 LLVMBuildStore(g->builder, elem, elem_ptr);
7631 }
7632 }
7633 return result_loc;
7634}
7635
7636static LLVMValueRef ir_render_array_to_vector(CodeGen *g, Stage1Air *executable,
7637 Stage1AirInstArrayToVector *instruction)
7638{
7639 ZigType *vector_type = instruction->base.value->type;
7640 assert(vector_type->id == ZigTypeIdVector);
7641 assert(!handle_is_ptr(g, vector_type));
7642 LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);
7643 LLVMTypeRef vector_type_ref = get_llvm_type(g, vector_type);
7644
7645 ZigType *elem_type = vector_type->data.vector.elem_type;
7646 bool bitcast_ok = elem_type->size_in_bits == elem_type->abi_size * 8;
7647 ZigType *array_type = instruction->array->value->type;
7648 ir_assert(array_type->id == ZigTypeIdArray, &instruction->base);
7649 if (bitcast_ok) {
7650 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,
7651 LLVMPointerType(vector_type_ref, 0), "");
7652 uint32_t alignment = get_abi_alignment(g, array_type->data.array.child_type);
7653 return gen_load_untyped(g, vector_type_ref, casted_ptr, alignment, false, "");
7654 } else {
7655 // If the ABI size of the element type is not evenly divisible by size_in_bits, a simple bitcast
7656 // will not work, and we fall back to insertelement.
7657 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
7658 LLVMTypeRef u32_type_ref = LLVMInt32Type();
7659 LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false);
7660 LLVMValueRef vector = LLVMGetUndef(vector_type_ref);
7661 LLVMTypeRef array_llvm_ty = get_llvm_type(g, array_type);
7662 LLVMTypeRef elem_llvm_ty = get_llvm_type(g, elem_type);
7663 for (uintptr_t i = 0; i < instruction->base.value->type->data.vector.len; i++) {
7664 LLVMValueRef index_usize = LLVMConstInt(usize_type_ref, i, false);
7665 LLVMValueRef index_u32 = LLVMConstInt(u32_type_ref, i, false);
7666 LLVMValueRef indexes[] = { zero, index_usize };
7667 LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP2(g->builder, array_llvm_ty, array_ptr,
7668 indexes, 2, "");
7669 LLVMValueRef elem = LLVMBuildLoad2(g->builder, elem_llvm_ty, elem_ptr, "");
7670 vector = LLVMBuildInsertElement(g->builder, vector, elem, index_u32, "");
7671 }
7672 return vector;
7673 }
7674}
7675
7676static LLVMValueRef ir_render_assert_zero(CodeGen *g, Stage1Air *executable,
7677 Stage1AirInstAssertZero *instruction)
7678{
7679 LLVMValueRef target = ir_llvm_value(g, instruction->target);
7680 ZigType *int_type = instruction->target->value->type;
7681 if (ir_want_runtime_safety(g, &instruction->base)) {
7682 return gen_assert_zero(g, target, int_type);
7683 }
7684 return nullptr;
7685}
7686
7687static LLVMValueRef ir_render_assert_non_null(CodeGen *g, Stage1Air *executable,
7688 Stage1AirInstAssertNonNull *instruction)
7689{
7690 LLVMValueRef target = ir_llvm_value(g, instruction->target);
7691 ZigType *target_type = instruction->target->value->type;
7692
7693 if (target_type->id == ZigTypeIdPointer) {
7694 assert(target_type->data.pointer.ptr_len == PtrLenC);
7695 LLVMValueRef non_null_bit = LLVMBuildICmp(g->builder, LLVMIntNE, target,
7696 LLVMConstNull(get_llvm_type(g, target_type)), "");
7697
7698 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "AssertNonNullFail");
7699 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "AssertNonNullOk");
7700 LLVMBuildCondBr(g->builder, non_null_bit, ok_block, fail_block);
7701
7702 LLVMPositionBuilderAtEnd(g->builder, fail_block);
7703 gen_assertion(g, PanicMsgIdUnwrapOptionalFail, &instruction->base);
7704
7705 LLVMPositionBuilderAtEnd(g->builder, ok_block);
7706 } else {
7707 zig_unreachable();
7708 }
7709 return nullptr;
7710}
7711
7712static LLVMValueRef ir_render_suspend_begin(CodeGen *g, Stage1Air *executable,
7713 Stage1AirInstSuspendBegin *instruction)
7714{
7715 if (fn_is_async(g->cur_fn)) {
7716 instruction->resume_bb = gen_suspend_begin(g, "SuspendResume");
7717 }
7718 return nullptr;
7719}
7720
7721static LLVMValueRef ir_render_suspend_finish(CodeGen *g, Stage1Air *executable,
7722 Stage1AirInstSuspendFinish *instruction)
7723{
7724 LLVMBuildRetVoid(g->builder);
7725
7726 LLVMPositionBuilderAtEnd(g->builder, instruction->begin->resume_bb);
7727 if (ir_want_runtime_safety(g, &instruction->base)) {
7728 LLVMBuildStore(g->builder, g->cur_bad_not_suspended_index, g->cur_async_resume_index_ptr);
7729 }
7730 render_async_var_decls(g, instruction->base.scope);
7731 return nullptr;
7732}
7733
7734static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_instr,
7735 LLVMTypeRef target_frame_struct_llvm_ty, LLVMValueRef target_frame_ptr,
7736 ZigType *result_type, ZigType *ptr_result_type, LLVMValueRef result_loc, bool non_async)
7737{
7738 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
7739 LLVMValueRef their_result_ptr = nullptr;
7740 if (type_has_bits(g, result_type) && (non_async || result_loc != nullptr)) {
7741 LLVMValueRef their_result_ptr_ptr = LLVMBuildStructGEP2(g->builder,
7742 target_frame_struct_llvm_ty, target_frame_ptr, frame_ret_start, "");
7743 their_result_ptr = LLVMBuildLoad2(g->builder,
7744 ZigLLVMGetGEPResultElementType(their_result_ptr_ptr), their_result_ptr_ptr, "");
7745 if (result_loc != nullptr) {
7746 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
7747 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, result_loc, ptr_u8, "");
7748 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, their_result_ptr, ptr_u8, "");
7749 bool is_volatile = false;
7750 uint32_t abi_align = get_abi_alignment(g, result_type);
7751 LLVMValueRef byte_count_val = LLVMConstInt(usize_type_ref, type_size(g, result_type), false);
7752 ZigLLVMBuildMemCpy(g->builder,
7753 dest_ptr_casted, abi_align,
7754 src_ptr_casted, abi_align, byte_count_val, is_volatile);
7755 }
7756 }
7757 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {
7758 LLVMValueRef their_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder,
7759 target_frame_struct_llvm_ty, target_frame_ptr,
7760 frame_index_trace_arg(g, result_type), "");
7761 LLVMValueRef src_trace_ptr = LLVMBuildLoad2(g->builder,
7762 ZigLLVMGetGEPResultElementType(their_trace_ptr_ptr), their_trace_ptr_ptr, "");
7763 bool is_llvm_alloca;
7764 LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->scope, &is_llvm_alloca);
7765 LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr };
7766 ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(get_merge_err_ret_traces_fn_val(g)),
7767 get_merge_err_ret_traces_fn_val(g), args, 2,
7768 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
7769 }
7770 if (non_async && type_has_bits(g, result_type)) {
7771 LLVMValueRef result_ptr = (result_loc == nullptr) ? their_result_ptr : result_loc;
7772 return get_handle_value(g, result_ptr, result_type, ptr_result_type);
7773 } else {
7774 return nullptr;
7775 }
7776}
7777
7778static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, Stage1AirInstAwait *instruction) {
7779 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
7780 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
7781 LLVMValueRef target_frame_ptr = ir_llvm_value(g, instruction->frame);
7782 ir_assert(instruction->frame->value->type->id == ZigTypeIdAnyFrame, &instruction->base);
7783 LLVMTypeRef target_frame_llvm_ty = instruction->frame->value->type->data.any_frame.struct_llvm_ty;
7784 ZigType *result_type = instruction->base.value->type;
7785 ZigType *ptr_result_type = get_pointer_to_type(g, result_type, true);
7786
7787 LLVMValueRef result_loc = (instruction->result_loc == nullptr) ?
7788 nullptr : ir_llvm_value(g, instruction->result_loc);
7789
7790 if (instruction->is_nosuspend ||
7791 (instruction->target_fn != nullptr && !fn_is_async(instruction->target_fn)))
7792 {
7793 return gen_await_early_return(g, &instruction->base, target_frame_llvm_ty,
7794 target_frame_ptr, result_type, ptr_result_type, result_loc, true);
7795 }
7796
7797 // Prepare to be suspended
7798 LLVMBasicBlockRef resume_bb = gen_suspend_begin(g, "AwaitResume");
7799 LLVMBasicBlockRef end_bb = LLVMAppendBasicBlock(g->cur_fn_val, "AwaitEnd");
7800
7801 // At this point resuming the function will continue from resume_bb.
7802 // This code is as if it is running inside the suspend block.
7803
7804 // supply the awaiter return pointer
7805 if (type_has_bits(g, result_type)) {
7806 LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP2(g->builder, target_frame_llvm_ty,
7807 target_frame_ptr, frame_ret_start + 1, "");
7808 if (result_loc == nullptr) {
7809 // no copy needed
7810 LLVMBuildStore(g->builder, LLVMConstNull(ZigLLVMGetGEPResultElementType(awaiter_ret_ptr_ptr)),
7811 awaiter_ret_ptr_ptr);
7812 } else {
7813 LLVMBuildStore(g->builder, result_loc, awaiter_ret_ptr_ptr);
7814 }
7815 }
7816
7817 // supply the error return trace pointer
7818 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {
7819 bool is_llvm_alloca;
7820 LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca);
7821 assert(my_err_ret_trace_val != nullptr);
7822 LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, target_frame_llvm_ty,
7823 target_frame_ptr, frame_index_trace_arg(g, result_type) + 1, "");
7824 LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr);
7825 }
7826
7827 // caller's own frame pointer
7828 LLVMValueRef awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, "");
7829 LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, target_frame_llvm_ty,
7830 target_frame_ptr, frame_awaiter_index, "");
7831 LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_init_val,
7832 LLVMAtomicOrderingRelease);
7833
7834 LLVMBasicBlockRef bad_await_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadAwait");
7835 LLVMBasicBlockRef complete_suspend_block = LLVMAppendBasicBlock(g->cur_fn_val, "CompleteSuspend");
7836 LLVMBasicBlockRef early_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "EarlyReturn");
7837
7838 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);
7839 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, prev_val, bad_await_block, 2);
7840
7841 LLVMAddCase(switch_instr, zero, complete_suspend_block);
7842 LLVMAddCase(switch_instr, all_ones, early_return_block);
7843
7844 // We discovered that another awaiter was already here.
7845 LLVMPositionBuilderAtEnd(g->builder, bad_await_block);
7846 gen_assertion(g, PanicMsgIdBadAwait, &instruction->base);
7847
7848 // Rely on the target to resume us from suspension.
7849 LLVMPositionBuilderAtEnd(g->builder, complete_suspend_block);
7850 LLVMBuildRetVoid(g->builder);
7851
7852 // Early return: The async function has already completed. We must copy the result and
7853 // the error return trace if applicable.
7854 LLVMPositionBuilderAtEnd(g->builder, early_return_block);
7855 gen_await_early_return(g, &instruction->base, target_frame_llvm_ty, target_frame_ptr,
7856 result_type, ptr_result_type, result_loc, false);
7857 LLVMBuildBr(g->builder, end_bb);
7858
7859 LLVMPositionBuilderAtEnd(g->builder, resume_bb);
7860 gen_assert_resume_id(g, &instruction->base, ResumeIdReturn, PanicMsgIdResumedAnAwaitingFn, nullptr);
7861 LLVMBuildBr(g->builder, end_bb);
7862
7863 LLVMPositionBuilderAtEnd(g->builder, end_bb);
7864 // Rely on the spill for the llvm_value to be populated.
7865 // See the implementation of ir_llvm_value.
7866 return nullptr;
7867}
7868
7869static LLVMValueRef ir_render_resume(CodeGen *g, Stage1Air *executable, Stage1AirInstResume *instruction) {
7870 LLVMValueRef frame = ir_llvm_value(g, instruction->frame);
7871 ZigType *frame_type = instruction->frame->value->type;
7872 assert(frame_type->id == ZigTypeIdAnyFrame);
7873
7874 gen_resume(g, g->anyframe_fn_type, nullptr, frame, ResumeIdManual);
7875 return nullptr;
7876}
7877
7878static LLVMValueRef ir_render_frame_size(CodeGen *g, Stage1Air *executable,
7879 Stage1AirInstFrameSize *instruction)
7880{
7881 LLVMValueRef fn_val = ir_llvm_value(g, instruction->fn);
7882 return gen_frame_size(g, fn_val);
7883}
7884
7885static LLVMValueRef ir_render_spill_begin(CodeGen *g, Stage1Air *executable,
7886 Stage1AirInstSpillBegin *instruction)
7887{
7888 if (!fn_is_async(g->cur_fn))
7889 return nullptr;
7890
7891 switch (instruction->spill_id) {
7892 case SpillIdInvalid:
7893 zig_unreachable();
7894 case SpillIdRetErrCode: {
7895 LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
7896 LLVMValueRef ptr = ir_llvm_value(g, g->cur_fn->err_code_spill);
7897 LLVMBuildStore(g->builder, operand, ptr);
7898 return nullptr;
7899 }
7900
7901 }
7902 zig_unreachable();
7903}
7904
7905static LLVMValueRef ir_render_spill_end(CodeGen *g, Stage1Air *executable, Stage1AirInstSpillEnd *instruction) {
7906 if (!fn_is_async(g->cur_fn))
7907 return ir_llvm_value(g, instruction->begin->operand);
7908
7909 switch (instruction->begin->spill_id) {
7910 case SpillIdInvalid:
7911 zig_unreachable();
7912 case SpillIdRetErrCode: {
7913 LLVMValueRef ptr = ir_llvm_value(g, g->cur_fn->err_code_spill);
7914 LLVMTypeRef llvm_ty = g->builtin_types.entry_global_error_set->llvm_type;
7915 return LLVMBuildLoad2(g->builder, llvm_ty, ptr, "");
7916 }
7917
7918 }
7919 zig_unreachable();
7920}
7921
7922static LLVMValueRef ir_render_vector_extract_elem(CodeGen *g, Stage1Air *executable,
7923 Stage1AirInstVectorExtractElem *instruction)
7924{
7925 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
7926 LLVMValueRef index = ir_llvm_value(g, instruction->index);
7927 return LLVMBuildExtractElement(g->builder, vector, index, "");
7928}
7929
7930static void set_debug_location(CodeGen *g, Stage1AirInst *instruction) {
7931 AstNode *source_node = instruction->source_node;
7932 Scope *scope = instruction->scope;
7933
7934 assert(source_node);
7935 assert(scope);
7936
7937 ZigLLVMSetCurrentDebugLocation(g->builder, node_line_onebased(source_node),
7938 node_column_onebased(source_node), get_di_scope(g, scope));
7939}
7940
7941static LLVMValueRef ir_render_instruction(CodeGen *g, Stage1Air *executable, Stage1AirInst *instruction) {
7942 switch (instruction->id) {
7943 case Stage1AirInstIdInvalid:
7944 case Stage1AirInstIdConst:
7945 case Stage1AirInstIdAlloca:
7946 zig_unreachable();
7947
7948 case Stage1AirInstIdDeclVar:
7949 return ir_render_decl_var(g, executable, (Stage1AirInstDeclVar *)instruction);
7950 case Stage1AirInstIdReturn:
7951 return ir_render_return(g, executable, (Stage1AirInstReturn *)instruction);
7952 case Stage1AirInstIdBinOp:
7953 return ir_render_bin_op(g, executable, (Stage1AirInstBinOp *)instruction);
7954 case Stage1AirInstIdCast:
7955 return ir_render_cast(g, executable, (Stage1AirInstCast *)instruction);
7956 case Stage1AirInstIdUnreachable:
7957 return ir_render_unreachable(g, executable, (Stage1AirInstUnreachable *)instruction);
7958 case Stage1AirInstIdCondBr:
7959 return ir_render_cond_br(g, executable, (Stage1AirInstCondBr *)instruction);
7960 case Stage1AirInstIdBr:
7961 return ir_render_br(g, executable, (Stage1AirInstBr *)instruction);
7962 case Stage1AirInstIdBinaryNot:
7963 return ir_render_binary_not(g, executable, (Stage1AirInstBinaryNot *)instruction);
7964 case Stage1AirInstIdNegation:
7965 return ir_render_negation(g, executable, (Stage1AirInstNegation *)instruction);
7966 case Stage1AirInstIdLoadPtr:
7967 return ir_render_load_ptr(g, executable, (Stage1AirInstLoadPtr *)instruction);
7968 case Stage1AirInstIdStorePtr:
7969 return ir_render_store_ptr(g, executable, (Stage1AirInstStorePtr *)instruction);
7970 case Stage1AirInstIdVectorStoreElem:
7971 return ir_render_vector_store_elem(g, executable, (Stage1AirInstVectorStoreElem *)instruction);
7972 case Stage1AirInstIdVarPtr:
7973 return ir_render_var_ptr(g, executable, (Stage1AirInstVarPtr *)instruction);
7974 case Stage1AirInstIdReturnPtr:
7975 return ir_render_return_ptr(g, executable, (Stage1AirInstReturnPtr *)instruction);
7976 case Stage1AirInstIdElemPtr:
7977 return ir_render_elem_ptr(g, executable, (Stage1AirInstElemPtr *)instruction);
7978 case Stage1AirInstIdCall:
7979 return ir_render_call(g, executable, (Stage1AirInstCall *)instruction);
7980 case Stage1AirInstIdStructFieldPtr:
7981 return ir_render_struct_field_ptr(g, executable, (Stage1AirInstStructFieldPtr *)instruction);
7982 case Stage1AirInstIdUnionFieldPtr:
7983 return ir_render_union_field_ptr(g, executable, (Stage1AirInstUnionFieldPtr *)instruction);
7984 case Stage1AirInstIdAsm:
7985 return ir_render_asm_gen(g, executable, (Stage1AirInstAsm *)instruction);
7986 case Stage1AirInstIdTestNonNull:
7987 return ir_render_test_non_null(g, executable, (Stage1AirInstTestNonNull *)instruction);
7988 case Stage1AirInstIdOptionalUnwrapPtr:
7989 return ir_render_optional_unwrap_ptr(g, executable, (Stage1AirInstOptionalUnwrapPtr *)instruction);
7990 case Stage1AirInstIdClz:
7991 return ir_render_clz(g, executable, (Stage1AirInstClz *)instruction);
7992 case Stage1AirInstIdCtz:
7993 return ir_render_ctz(g, executable, (Stage1AirInstCtz *)instruction);
7994 case Stage1AirInstIdPopCount:
7995 return ir_render_pop_count(g, executable, (Stage1AirInstPopCount *)instruction);
7996 case Stage1AirInstIdSwitchBr:
7997 return ir_render_switch_br(g, executable, (Stage1AirInstSwitchBr *)instruction);
7998 case Stage1AirInstIdBswap:
7999 return ir_render_bswap(g, executable, (Stage1AirInstBswap *)instruction);
8000 case Stage1AirInstIdBitReverse:
8001 return ir_render_bit_reverse(g, executable, (Stage1AirInstBitReverse *)instruction);
8002 case Stage1AirInstIdPhi:
8003 return ir_render_phi(g, executable, (Stage1AirInstPhi *)instruction);
8004 case Stage1AirInstIdRef:
8005 return ir_render_ref(g, executable, (Stage1AirInstRef *)instruction);
8006 case Stage1AirInstIdErrName:
8007 return ir_render_err_name(g, executable, (Stage1AirInstErrName *)instruction);
8008 case Stage1AirInstIdCmpxchg:
8009 return ir_render_cmpxchg(g, executable, (Stage1AirInstCmpxchg *)instruction);
8010 case Stage1AirInstIdFence:
8011 return ir_render_fence(g, executable, (Stage1AirInstFence *)instruction);
8012 case Stage1AirInstIdReduce:
8013 return ir_render_reduce(g, executable, (Stage1AirInstReduce *)instruction);
8014 case Stage1AirInstIdTruncate:
8015 return ir_render_truncate(g, executable, (Stage1AirInstTruncate *)instruction);
8016 case Stage1AirInstIdBoolNot:
8017 return ir_render_bool_not(g, executable, (Stage1AirInstBoolNot *)instruction);
8018 case Stage1AirInstIdMemset:
8019 return ir_render_memset(g, executable, (Stage1AirInstMemset *)instruction);
8020 case Stage1AirInstIdMemcpy:
8021 return ir_render_memcpy(g, executable, (Stage1AirInstMemcpy *)instruction);
8022 case Stage1AirInstIdSlice:
8023 return ir_render_slice(g, executable, (Stage1AirInstSlice *)instruction);
8024 case Stage1AirInstIdBreakpoint:
8025 return ir_render_breakpoint(g, executable, (Stage1AirInstBreakpoint *)instruction);
8026 case Stage1AirInstIdReturnAddress:
8027 return ir_render_return_address(g, executable, (Stage1AirInstReturnAddress *)instruction);
8028 case Stage1AirInstIdFrameAddress:
8029 return ir_render_frame_address(g, executable, (Stage1AirInstFrameAddress *)instruction);
8030 case Stage1AirInstIdFrameHandle:
8031 return ir_render_handle(g, executable, (Stage1AirInstFrameHandle *)instruction);
8032 case Stage1AirInstIdOverflowOp:
8033 return ir_render_overflow_op(g, executable, (Stage1AirInstOverflowOp *)instruction);
8034 case Stage1AirInstIdTestErr:
8035 return ir_render_test_err(g, executable, (Stage1AirInstTestErr *)instruction);
8036 case Stage1AirInstIdUnwrapErrCode:
8037 return ir_render_unwrap_err_code(g, executable, (Stage1AirInstUnwrapErrCode *)instruction);
8038 case Stage1AirInstIdUnwrapErrPayload:
8039 return ir_render_unwrap_err_payload(g, executable, (Stage1AirInstUnwrapErrPayload *)instruction);
8040 case Stage1AirInstIdOptionalWrap:
8041 return ir_render_optional_wrap(g, executable, (Stage1AirInstOptionalWrap *)instruction);
8042 case Stage1AirInstIdErrWrapCode:
8043 return ir_render_err_wrap_code(g, executable, (Stage1AirInstErrWrapCode *)instruction);
8044 case Stage1AirInstIdErrWrapPayload:
8045 return ir_render_err_wrap_payload(g, executable, (Stage1AirInstErrWrapPayload *)instruction);
8046 case Stage1AirInstIdUnionTag:
8047 return ir_render_union_tag(g, executable, (Stage1AirInstUnionTag *)instruction);
8048 case Stage1AirInstIdPtrCast:
8049 return ir_render_ptr_cast(g, executable, (Stage1AirInstPtrCast *)instruction);
8050 case Stage1AirInstIdBitCast:
8051 return ir_render_bit_cast(g, executable, (Stage1AirInstBitCast *)instruction);
8052 case Stage1AirInstIdWidenOrShorten:
8053 return ir_render_widen_or_shorten(g, executable, (Stage1AirInstWidenOrShorten *)instruction);
8054 case Stage1AirInstIdPtrToInt:
8055 return ir_render_ptr_to_int(g, executable, (Stage1AirInstPtrToInt *)instruction);
8056 case Stage1AirInstIdIntToPtr:
8057 return ir_render_int_to_ptr(g, executable, (Stage1AirInstIntToPtr *)instruction);
8058 case Stage1AirInstIdIntToEnum:
8059 return ir_render_int_to_enum(g, executable, (Stage1AirInstIntToEnum *)instruction);
8060 case Stage1AirInstIdIntToErr:
8061 return ir_render_int_to_err(g, executable, (Stage1AirInstIntToErr *)instruction);
8062 case Stage1AirInstIdErrToInt:
8063 return ir_render_err_to_int(g, executable, (Stage1AirInstErrToInt *)instruction);
8064 case Stage1AirInstIdPanic:
8065 return ir_render_panic(g, executable, (Stage1AirInstPanic *)instruction);
8066 case Stage1AirInstIdTagName:
8067 return ir_render_enum_tag_name(g, executable, (Stage1AirInstTagName *)instruction);
8068 case Stage1AirInstIdFieldParentPtr:
8069 return ir_render_field_parent_ptr(g, executable, (Stage1AirInstFieldParentPtr *)instruction);
8070 case Stage1AirInstIdAlignCast:
8071 return ir_render_align_cast(g, executable, (Stage1AirInstAlignCast *)instruction);
8072 case Stage1AirInstIdErrorReturnTrace:
8073 return ir_render_error_return_trace(g, executable, (Stage1AirInstErrorReturnTrace *)instruction);
8074 case Stage1AirInstIdAtomicRmw:
8075 return ir_render_atomic_rmw(g, executable, (Stage1AirInstAtomicRmw *)instruction);
8076 case Stage1AirInstIdAtomicLoad:
8077 return ir_render_atomic_load(g, executable, (Stage1AirInstAtomicLoad *)instruction);
8078 case Stage1AirInstIdAtomicStore:
8079 return ir_render_atomic_store(g, executable, (Stage1AirInstAtomicStore *)instruction);
8080 case Stage1AirInstIdSaveErrRetAddr:
8081 return ir_render_save_err_ret_addr(g, executable, (Stage1AirInstSaveErrRetAddr *)instruction);
8082 case Stage1AirInstIdFloatOp:
8083 return ir_render_float_op(g, executable, (Stage1AirInstFloatOp *)instruction);
8084 case Stage1AirInstIdMulAdd:
8085 return ir_render_mul_add(g, executable, (Stage1AirInstMulAdd *)instruction);
8086 case Stage1AirInstIdArrayToVector:
8087 return ir_render_array_to_vector(g, executable, (Stage1AirInstArrayToVector *)instruction);
8088 case Stage1AirInstIdVectorToArray:
8089 return ir_render_vector_to_array(g, executable, (Stage1AirInstVectorToArray *)instruction);
8090 case Stage1AirInstIdAssertZero:
8091 return ir_render_assert_zero(g, executable, (Stage1AirInstAssertZero *)instruction);
8092 case Stage1AirInstIdAssertNonNull:
8093 return ir_render_assert_non_null(g, executable, (Stage1AirInstAssertNonNull *)instruction);
8094 case Stage1AirInstIdPtrOfArrayToSlice:
8095 return ir_render_ptr_of_array_to_slice(g, executable, (Stage1AirInstPtrOfArrayToSlice *)instruction);
8096 case Stage1AirInstIdSuspendBegin:
8097 return ir_render_suspend_begin(g, executable, (Stage1AirInstSuspendBegin *)instruction);
8098 case Stage1AirInstIdSuspendFinish:
8099 return ir_render_suspend_finish(g, executable, (Stage1AirInstSuspendFinish *)instruction);
8100 case Stage1AirInstIdResume:
8101 return ir_render_resume(g, executable, (Stage1AirInstResume *)instruction);
8102 case Stage1AirInstIdFrameSize:
8103 return ir_render_frame_size(g, executable, (Stage1AirInstFrameSize *)instruction);
8104 case Stage1AirInstIdAwait:
8105 return ir_render_await(g, executable, (Stage1AirInstAwait *)instruction);
8106 case Stage1AirInstIdSpillBegin:
8107 return ir_render_spill_begin(g, executable, (Stage1AirInstSpillBegin *)instruction);
8108 case Stage1AirInstIdSpillEnd:
8109 return ir_render_spill_end(g, executable, (Stage1AirInstSpillEnd *)instruction);
8110 case Stage1AirInstIdShuffleVector:
8111 return ir_render_shuffle_vector(g, executable, (Stage1AirInstShuffleVector *) instruction);
8112 case Stage1AirInstIdSelect:
8113 return ir_render_select(g, executable, (Stage1AirInstSelect *) instruction);
8114 case Stage1AirInstIdSplat:
8115 return ir_render_splat(g, executable, (Stage1AirInstSplat *) instruction);
8116 case Stage1AirInstIdVectorExtractElem:
8117 return ir_render_vector_extract_elem(g, executable, (Stage1AirInstVectorExtractElem *) instruction);
8118 case Stage1AirInstIdWasmMemorySize:
8119 return ir_render_wasm_memory_size(g, executable, (Stage1AirInstWasmMemorySize *) instruction);
8120 case Stage1AirInstIdWasmMemoryGrow:
8121 return ir_render_wasm_memory_grow(g, executable, (Stage1AirInstWasmMemoryGrow *) instruction);
8122 case Stage1AirInstIdExtern:
8123 return ir_render_extern(g, executable, (Stage1AirInstExtern *) instruction);
8124 case Stage1AirInstIdPrefetch:
8125 return ir_render_prefetch(g, executable, (Stage1AirInstPrefetch *) instruction);
8126 }
8127 zig_unreachable();
8128}
8129
8130static void ir_render(CodeGen *g, ZigFn *fn_entry) {
8131 assert(fn_entry);
8132
8133 Stage1Air *executable = &fn_entry->analyzed_executable;
8134 assert(executable->basic_block_list.length > 0);
8135
8136 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
8137 Stage1AirBasicBlock *current_block = executable->basic_block_list.at(block_i);
8138 if (get_scope_typeof(current_block->scope) != nullptr) {
8139 LLVMBuildBr(g->builder, current_block->llvm_block);
8140 }
8141 assert(current_block->llvm_block);
8142 LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);
8143 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
8144 Stage1AirInst *instruction = current_block->instruction_list.at(instr_i);
8145 if (instruction->ref_count == 0 && !ir_inst_gen_has_side_effects(instruction))
8146 continue;
8147 if (get_scope_typeof(instruction->scope) != nullptr)
8148 continue;
8149
8150 if (!g->strip_debug_symbols) {
8151 set_debug_location(g, instruction);
8152 }
8153 instruction->llvm_value = ir_render_instruction(g, executable, instruction);
8154 if (instruction->spill != nullptr && instruction->llvm_value != nullptr) {
8155 LLVMValueRef spill_ptr = ir_llvm_value(g, instruction->spill);
8156 gen_assign_raw(g, spill_ptr, instruction->spill->value->type, instruction->llvm_value);
8157 instruction->llvm_value = nullptr;
8158 }
8159 }
8160 current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder);
8161 }
8162}
8163
8164static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ZigValue *struct_const_val, size_t field_index);
8165static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ZigValue *array_const_val, size_t index);
8166static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ZigValue *union_const_val);
8167static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ZigValue *err_union_const_val);
8168static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ZigValue *err_union_const_val);
8169static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ZigValue *optional_const_val);
8170
8171static LLVMValueRef gen_parent_ptr(CodeGen *g, ZigValue *val, ConstParent *parent) {
8172 switch (parent->id) {
8173 case ConstParentIdNone:
8174 render_const_val(g, val, "");
8175 render_const_val_global(g, val, "");
8176 return val->llvm_global;
8177 case ConstParentIdStruct: {
8178 ZigValue *struct_val = parent->data.p_struct.struct_val;
8179 size_t src_field_index = parent->data.p_struct.field_index;
8180 size_t gen_field_index = struct_val->type->data.structure.fields[src_field_index]->gen_index;
8181 return gen_const_ptr_struct_recursive(g, struct_val, gen_field_index);
8182 }
8183 case ConstParentIdErrUnionCode:
8184 return gen_const_ptr_err_union_code_recursive(g, parent->data.p_err_union_code.err_union_val);
8185 case ConstParentIdErrUnionPayload:
8186 return gen_const_ptr_err_union_payload_recursive(g, parent->data.p_err_union_payload.err_union_val);
8187 case ConstParentIdOptionalPayload:
8188 return gen_const_ptr_optional_payload_recursive(g, parent->data.p_optional_payload.optional_val);
8189 case ConstParentIdArray:
8190 return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,
8191 parent->data.p_array.elem_index);
8192 case ConstParentIdUnion:
8193 return gen_const_ptr_union_recursive(g, parent->data.p_union.union_val);
8194 case ConstParentIdScalar:
8195 render_const_val(g, parent->data.p_scalar.scalar_val, "");
8196 render_const_val_global(g, parent->data.p_scalar.scalar_val, "");
8197 return parent->data.p_scalar.scalar_val->llvm_global;
8198 }
8199 zig_unreachable();
8200}
8201
8202static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ZigValue *array_const_val, size_t index) {
8203 expand_undef_array(g, array_const_val);
8204 ConstParent *parent = &array_const_val->parent;
8205 LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
8206
8207 ZigType *usize = g->builtin_types.entry_usize;
8208 LLVMTypeRef array_llvm_ty = get_llvm_type(g, array_const_val->type);
8209 LLVMValueRef casted_base_ptr = LLVMConstBitCast(base_ptr, LLVMPointerType(array_llvm_ty, 0));
8210 LLVMValueRef indices[] = {
8211 LLVMConstNull(usize->llvm_type),
8212 LLVMConstInt(usize->llvm_type, index, false),
8213 };
8214 return LLVMConstInBoundsGEP2(array_llvm_ty, casted_base_ptr, indices, 2);
8215}
8216
8217static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ZigValue *struct_const_val, size_t field_index) {
8218 ConstParent *parent = &struct_const_val->parent;
8219 LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);
8220
8221 LLVMValueRef indices[] = {
8222 LLVMConstNull(LLVMInt32Type()),
8223 LLVMConstInt(LLVMInt32Type(), field_index, false),
8224 };
8225
8226 // The structure pointed by base_ptr may include trailing padding for
8227 // alignment purposes and have the following LLVM type: <{ %T, [N x i8] }>.
8228 // Add an extra bitcast as we're only interested in the %T part.
8229 assert(handle_is_ptr(g, struct_const_val->type));
8230
8231 LLVMTypeRef struct_llvm_ty = get_llvm_type(g, struct_const_val->type);
8232 LLVMValueRef casted_base_ptr = LLVMConstBitCast(base_ptr, LLVMPointerType(struct_llvm_ty, 0));
8233 return LLVMConstInBoundsGEP2(struct_llvm_ty, casted_base_ptr, indices, 2);
8234}
8235
8236static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ZigValue *err_union_const_val) {
8237 ConstParent *parent = &err_union_const_val->parent;
8238 LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
8239
8240 ZigType *u32 = g->builtin_types.entry_u32;
8241 LLVMValueRef indices[] = {
8242 LLVMConstNull(get_llvm_type(g, u32)),
8243 LLVMConstInt(get_llvm_type(g, u32), err_union_err_index, false),
8244 };
8245 return LLVMConstInBoundsGEP2(get_llvm_type(g, err_union_const_val->type), base_ptr, indices, 2);
8246}
8247
8248static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ZigValue *err_union_const_val) {
8249 ConstParent *parent = &err_union_const_val->parent;
8250 LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
8251
8252 ZigType *u32 = g->builtin_types.entry_u32;
8253 LLVMValueRef indices[] = {
8254 LLVMConstNull(get_llvm_type(g, u32)),
8255 LLVMConstInt(get_llvm_type(g, u32), err_union_payload_index, false),
8256 };
8257 return LLVMConstInBoundsGEP2(get_llvm_type(g, err_union_const_val->type), base_ptr, indices, 2);
8258}
8259
8260static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ZigValue *optional_const_val) {
8261 ConstParent *parent = &optional_const_val->parent;
8262 LLVMValueRef base_ptr = gen_parent_ptr(g, optional_const_val, parent);
8263
8264 ZigType *u32 = g->builtin_types.entry_u32;
8265 LLVMValueRef indices[] = {
8266 LLVMConstNull(get_llvm_type(g, u32)),
8267 LLVMConstInt(get_llvm_type(g, u32), maybe_child_index, false),
8268 };
8269 return LLVMConstInBoundsGEP2(get_llvm_type(g, optional_const_val->type), base_ptr, indices, 2);
8270}
8271
8272static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ZigValue *union_const_val) {
8273 ConstParent *parent = &union_const_val->parent;
8274 LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);
8275
8276 // Slot in the structure where the payload is stored, if equal to SIZE_MAX
8277 // the union has no tag and a single field and is collapsed into the field
8278 // itself
8279 size_t union_payload_index = union_const_val->type->data.unionation.gen_union_index;
8280
8281 ZigType *u32 = g->builtin_types.entry_u32;
8282 LLVMValueRef indices[] = {
8283 LLVMConstNull(get_llvm_type(g, u32)),
8284 LLVMConstInt(get_llvm_type(g, u32), union_payload_index, false),
8285 };
8286 return LLVMConstInBoundsGEP2(get_llvm_type(g, union_const_val->type), base_ptr, indices, (union_payload_index != SIZE_MAX) ? 2 : 1);
8287}
8288
8289static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ZigValue *const_val) {
8290 switch (const_val->special) {
8291 case ConstValSpecialLazy:
8292 case ConstValSpecialRuntime:
8293 zig_unreachable();
8294 case ConstValSpecialUndef:
8295 return LLVMConstInt(big_int_type_ref, 0, false);
8296 case ConstValSpecialStatic:
8297 break;
8298 }
8299
8300 ZigType *type_entry = const_val->type;
8301 assert(type_has_bits(g, type_entry));
8302 switch (type_entry->id) {
8303 case ZigTypeIdInvalid:
8304 case ZigTypeIdMetaType:
8305 case ZigTypeIdUnreachable:
8306 case ZigTypeIdComptimeFloat:
8307 case ZigTypeIdComptimeInt:
8308 case ZigTypeIdEnumLiteral:
8309 case ZigTypeIdUndefined:
8310 case ZigTypeIdNull:
8311 case ZigTypeIdErrorUnion:
8312 case ZigTypeIdErrorSet:
8313 case ZigTypeIdBoundFn:
8314 case ZigTypeIdVoid:
8315 case ZigTypeIdOpaque:
8316 zig_unreachable();
8317 case ZigTypeIdBool:
8318 return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false);
8319 case ZigTypeIdEnum:
8320 {
8321 assert(type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr);
8322 LLVMValueRef int_val = gen_const_val(g, const_val, "");
8323 return LLVMConstZExt(int_val, big_int_type_ref);
8324 }
8325 case ZigTypeIdInt:
8326 {
8327 LLVMValueRef int_val = gen_const_val(g, const_val, "");
8328 return LLVMConstZExt(int_val, big_int_type_ref);
8329 }
8330 case ZigTypeIdFloat:
8331 {
8332 LLVMValueRef float_val = gen_const_val(g, const_val, "");
8333 LLVMValueRef int_val = LLVMConstFPToUI(float_val,
8334 LLVMIntType((unsigned)type_entry->data.floating.bit_count));
8335 return LLVMConstZExt(int_val, big_int_type_ref);
8336 }
8337 case ZigTypeIdPointer:
8338 case ZigTypeIdFn:
8339 case ZigTypeIdOptional:
8340 {
8341 LLVMValueRef ptr_val = gen_const_val(g, const_val, "");
8342 LLVMValueRef ptr_size_int_val = LLVMConstPtrToInt(ptr_val, g->builtin_types.entry_usize->llvm_type);
8343 return LLVMConstZExt(ptr_size_int_val, big_int_type_ref);
8344 }
8345 case ZigTypeIdArray: {
8346 LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false);
8347 if (const_val->data.x_array.special == ConstArraySpecialUndef) {
8348 return val;
8349 }
8350 expand_undef_array(g, const_val);
8351 bool is_big_endian = g->is_big_endian; // TODO get endianness from struct type
8352 uint32_t packed_bits_size = type_size_bits(g, type_entry->data.array.child_type);
8353 size_t used_bits = 0;
8354 for (size_t i = 0; i < type_entry->data.array.len; i += 1) {
8355 ZigValue *elem_val = &const_val->data.x_array.data.s_none.elements[i];
8356 LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, elem_val);
8357
8358 if (is_big_endian) {
8359 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false);
8360 val = LLVMConstShl(val, shift_amt);
8361 val = LLVMConstOr(val, child_val);
8362 } else {
8363 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false);
8364 LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
8365 val = LLVMConstOr(val, child_val_shifted);
8366 used_bits += packed_bits_size;
8367 }
8368 }
8369
8370 if (type_entry->data.array.sentinel != nullptr) {
8371 ZigValue *elem_val = type_entry->data.array.sentinel;
8372 LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, elem_val);
8373
8374 if (is_big_endian) {
8375 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false);
8376 val = LLVMConstShl(val, shift_amt);
8377 val = LLVMConstOr(val, child_val);
8378 } else {
8379 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false);
8380 LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
8381 val = LLVMConstOr(val, child_val_shifted);
8382 used_bits += packed_bits_size;
8383 }
8384 }
8385 return val;
8386 }
8387 case ZigTypeIdVector:
8388 zig_panic("TODO bit pack a vector");
8389 case ZigTypeIdUnion:
8390 zig_panic("TODO bit pack a union");
8391 case ZigTypeIdStruct:
8392 {
8393 assert(type_entry->data.structure.layout == ContainerLayoutPacked);
8394 bool is_big_endian = g->is_big_endian; // TODO get endianness from struct type
8395
8396 LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false);
8397 size_t used_bits = 0;
8398 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
8399 TypeStructField *field = type_entry->data.structure.fields[i];
8400 if (field->gen_index == SIZE_MAX || field->is_comptime) {
8401 continue;
8402 }
8403 LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, const_val->data.x_struct.fields[i]);
8404 uint32_t packed_bits_size = type_size_bits(g, field->type_entry);
8405 if (is_big_endian) {
8406 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false);
8407 val = LLVMConstShl(val, shift_amt);
8408 val = LLVMConstOr(val, child_val);
8409 } else {
8410 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false);
8411 LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
8412 val = LLVMConstOr(val, child_val_shifted);
8413 used_bits += packed_bits_size;
8414 }
8415 }
8416 return val;
8417 }
8418 case ZigTypeIdFnFrame:
8419 zig_panic("TODO bit pack an async function frame");
8420 case ZigTypeIdAnyFrame:
8421 zig_panic("TODO bit pack an anyframe");
8422 }
8423 zig_unreachable();
8424}
8425
8426// We have this because union constants can't be represented by the official union type,
8427// and this property bubbles up in whatever aggregate type contains a union constant
8428static bool is_llvm_value_unnamed_type(CodeGen *g, ZigType *type_entry, LLVMValueRef val) {
8429 return LLVMTypeOf(val) != get_llvm_type(g, type_entry);
8430}
8431
8432static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const char *name) {
8433 switch (const_val->data.x_ptr.special) {
8434 case ConstPtrSpecialInvalid:
8435 case ConstPtrSpecialDiscard:
8436 zig_unreachable();
8437 case ConstPtrSpecialRef:
8438 {
8439 ZigValue *pointee = const_val->data.x_ptr.data.ref.pointee;
8440 render_const_val(g, pointee, "");
8441 render_const_val_global(g, pointee, "");
8442 const_val->llvm_value = LLVMConstBitCast(pointee->llvm_global,
8443 get_llvm_type(g, const_val->type));
8444 return const_val->llvm_value;
8445 }
8446 case ConstPtrSpecialBaseArray:
8447 case ConstPtrSpecialSubArray:
8448 {
8449 ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
8450 assert(array_const_val->type->id == ZigTypeIdArray);
8451 if (!type_has_bits(g, array_const_val->type)) {
8452 // make this a null pointer
8453 ZigType *usize = g->builtin_types.entry_usize;
8454 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
8455 get_llvm_type(g, const_val->type));
8456 return const_val->llvm_value;
8457 }
8458 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
8459 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);
8460 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type));
8461 const_val->llvm_value = ptr_val;
8462 return ptr_val;
8463 }
8464 case ConstPtrSpecialBaseStruct:
8465 {
8466 ZigValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val;
8467 assert(struct_const_val->type->id == ZigTypeIdStruct);
8468 if (!type_has_bits(g, struct_const_val->type)) {
8469 // make this a null pointer
8470 ZigType *usize = g->builtin_types.entry_usize;
8471 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
8472 get_llvm_type(g, const_val->type));
8473 return const_val->llvm_value;
8474 }
8475 size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index;
8476 size_t gen_field_index = struct_const_val->type->data.structure.fields[src_field_index]->gen_index;
8477 LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val,
8478 gen_field_index);
8479 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type));
8480 const_val->llvm_value = ptr_val;
8481 return ptr_val;
8482 }
8483 case ConstPtrSpecialBaseErrorUnionCode:
8484 {
8485 ZigValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_code.err_union_val;
8486 assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
8487 if (!type_has_bits(g, err_union_const_val->type)) {
8488 // make this a null pointer
8489 ZigType *usize = g->builtin_types.entry_usize;
8490 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
8491 get_llvm_type(g, const_val->type));
8492 return const_val->llvm_value;
8493 }
8494 LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_code_recursive(g, err_union_const_val);
8495 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type));
8496 const_val->llvm_value = ptr_val;
8497 return ptr_val;
8498 }
8499 case ConstPtrSpecialBaseErrorUnionPayload:
8500 {
8501 ZigValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val;
8502 assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
8503 if (!type_has_bits(g, err_union_const_val->type)) {
8504 // make this a null pointer
8505 ZigType *usize = g->builtin_types.entry_usize;
8506 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
8507 get_llvm_type(g, const_val->type));
8508 return const_val->llvm_value;
8509 }
8510 LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_payload_recursive(g, err_union_const_val);
8511 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type));
8512 const_val->llvm_value = ptr_val;
8513 return ptr_val;
8514 }
8515 case ConstPtrSpecialBaseOptionalPayload:
8516 {
8517 ZigValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val;
8518 assert(optional_const_val->type->id == ZigTypeIdOptional);
8519 if (!type_has_bits(g, optional_const_val->type)) {
8520 // make this a null pointer
8521 ZigType *usize = g->builtin_types.entry_usize;
8522 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
8523 get_llvm_type(g, const_val->type));
8524 return const_val->llvm_value;
8525 }
8526 LLVMValueRef uncasted_ptr_val = gen_const_ptr_optional_payload_recursive(g, optional_const_val);
8527 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type));
8528 const_val->llvm_value = ptr_val;
8529 return ptr_val;
8530 }
8531 case ConstPtrSpecialHardCodedAddr:
8532 {
8533 uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr;
8534 ZigType *usize = g->builtin_types.entry_usize;
8535 const_val->llvm_value = LLVMConstIntToPtr(
8536 LLVMConstInt(usize->llvm_type, addr_value, false), get_llvm_type(g, const_val->type));
8537 return const_val->llvm_value;
8538 }
8539 case ConstPtrSpecialFunction:
8540 return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry),
8541 get_llvm_type(g, const_val->type));
8542 case ConstPtrSpecialNull:
8543 return LLVMConstNull(get_llvm_type(g, const_val->type));
8544 }
8545 zig_unreachable();
8546}
8547
8548static LLVMValueRef gen_const_val_err_set(CodeGen *g, ZigValue *const_val, const char *name) {
8549 uint64_t value = (const_val->data.x_err_set == nullptr) ? 0 : const_val->data.x_err_set->value;
8550 return LLVMConstInt(get_llvm_type(g, g->builtin_types.entry_global_error_set), value, false);
8551}
8552
8553static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *name) {
8554 Error err;
8555
8556 ZigType *type_entry = const_val->type;
8557 assert(type_has_bits(g, type_entry));
8558
8559 if (const_val->special == ConstValSpecialLazy &&
8560 (err = ir_resolve_lazy(g, nullptr, const_val)))
8561 codegen_report_errors_and_exit(g);
8562
8563 switch (const_val->special) {
8564 case ConstValSpecialLazy:
8565 case ConstValSpecialRuntime:
8566 zig_unreachable();
8567 case ConstValSpecialUndef:
8568 return LLVMGetUndef(get_llvm_type(g, type_entry));
8569 case ConstValSpecialStatic:
8570 break;
8571 }
8572
8573 if ((err = type_resolve(g, type_entry, ResolveStatusLLVMFull)))
8574 zig_unreachable();
8575
8576 switch (type_entry->id) {
8577 case ZigTypeIdInt:
8578 return bigint_to_llvm_const(get_llvm_type(g, type_entry), &const_val->data.x_bigint);
8579 case ZigTypeIdErrorSet:
8580 return gen_const_val_err_set(g, const_val, name);
8581 case ZigTypeIdFloat:
8582 switch (type_entry->data.floating.bit_count) {
8583 case 16:
8584 {
8585 LLVMValueRef as_int = LLVMConstInt(LLVMInt16Type(), const_val->data.x_f16.v, false);
8586 return LLVMConstBitCast(as_int, get_llvm_type(g, type_entry));
8587 }
8588 case 32:
8589 return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f32);
8590 case 64:
8591 return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f64);
8592 case 80: {
8593 LLVMTypeRef llvm_i80 = LLVMIntType(80);
8594 LLVMValueRef x = LLVMConstInt(llvm_i80, const_val->data.x_f80.signExp, false);
8595 x = LLVMConstShl(x, LLVMConstInt(llvm_i80, 64, false));
8596 x = LLVMConstOr(x, LLVMConstInt(llvm_i80, const_val->data.x_f80.signif, false));
8597 if (target_has_f80(g->zig_target)) {
8598 return LLVMConstBitCast(x, LLVMX86FP80Type());
8599 } else {
8600 return x;
8601 }
8602 }
8603 case 128:
8604 {
8605 uint64_t buf[2];
8606
8607 // LLVM seems to require that the lower half of the f128 be
8608 // placed first in the buffer.
8609#if ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
8610 buf[0] = const_val->data.x_f128.v[0];
8611 buf[1] = const_val->data.x_f128.v[1];
8612#elif ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN
8613 buf[0] = const_val->data.x_f128.v[1];
8614 buf[1] = const_val->data.x_f128.v[0];
8615#else
8616#error Unsupported endian
8617#endif
8618
8619 LLVMValueRef as_int = LLVMConstIntOfArbitraryPrecision(LLVMInt128Type(), 2, buf);
8620 return LLVMConstBitCast(as_int, get_llvm_type(g, type_entry));
8621 }
8622 default:
8623 zig_unreachable();
8624 }
8625 case ZigTypeIdBool:
8626 if (const_val->data.x_bool) {
8627 return LLVMConstAllOnes(LLVMInt1Type());
8628 } else {
8629 return LLVMConstNull(LLVMInt1Type());
8630 }
8631 case ZigTypeIdOptional:
8632 {
8633 ZigType *child_type = type_entry->data.maybe.child_type;
8634
8635 if (get_src_ptr_type(type_entry) != nullptr) {
8636 bool has_bits;
8637 if ((err = type_has_bits2(g, child_type, &has_bits)))
8638 codegen_report_errors_and_exit(g);
8639
8640 if (has_bits)
8641 return gen_const_val_ptr(g, const_val, name);
8642
8643 // No bits, treat this value as a boolean
8644 const unsigned bool_val = optional_value_is_null(const_val) ? 0 : 1;
8645 return LLVMConstInt(LLVMInt1Type(), bool_val, false);
8646 } else if (child_type->id == ZigTypeIdErrorSet) {
8647 return gen_const_val_err_set(g, const_val, name);
8648 } else if (!type_has_bits(g, child_type)) {
8649 return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
8650 } else {
8651 LLVMValueRef child_val;
8652 LLVMValueRef maybe_val;
8653 bool make_unnamed_struct;
8654 if (const_val->data.x_optional) {
8655 child_val = gen_const_val(g, const_val->data.x_optional, "");
8656 maybe_val = LLVMConstAllOnes(LLVMInt1Type());
8657
8658 make_unnamed_struct = is_llvm_value_unnamed_type(g, const_val->type, child_val);
8659 } else {
8660 child_val = LLVMGetUndef(get_llvm_type(g, child_type));
8661 maybe_val = LLVMConstNull(LLVMInt1Type());
8662
8663 make_unnamed_struct = false;
8664 }
8665
8666 LLVMValueRef fields[] = {
8667 child_val,
8668 maybe_val,
8669 nullptr,
8670 };
8671 if (make_unnamed_struct) {
8672 LLVMValueRef result = LLVMConstStruct(fields, 2, false);
8673 uint64_t last_field_offset = LLVMOffsetOfElement(g->target_data_ref, LLVMTypeOf(result), 1);
8674 uint64_t end_offset = last_field_offset +
8675 LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(fields[1]));
8676 uint64_t expected_sz = LLVMABISizeOfType(g->target_data_ref, get_llvm_type(g, type_entry));
8677 unsigned pad_sz = expected_sz - end_offset;
8678 if (pad_sz != 0) {
8679 fields[2] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz));
8680 result = LLVMConstStruct(fields, 3, false);
8681 }
8682 uint64_t actual_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(result));
8683 assert(actual_sz == expected_sz);
8684 return result;
8685 } else {
8686 return LLVMConstNamedStruct(get_llvm_type(g, type_entry), fields, 2);
8687 }
8688 }
8689 }
8690 case ZigTypeIdStruct:
8691 {
8692 LLVMValueRef *fields = heap::c_allocator.allocate<LLVMValueRef>(type_entry->data.structure.gen_field_count);
8693 size_t src_field_count = type_entry->data.structure.src_field_count;
8694 bool make_unnamed_struct = false;
8695 assert(type_entry->data.structure.resolve_status == ResolveStatusLLVMFull);
8696 if (type_entry->data.structure.layout == ContainerLayoutPacked) {
8697 size_t src_field_index = 0;
8698 while (src_field_index < src_field_count) {
8699 TypeStructField *type_struct_field = type_entry->data.structure.fields[src_field_index];
8700 if (type_struct_field->gen_index == SIZE_MAX || type_struct_field->is_comptime) {
8701 src_field_index += 1;
8702 continue;
8703 }
8704
8705 size_t src_field_index_end = src_field_index + 1;
8706 for (; src_field_index_end < src_field_count; src_field_index_end += 1) {
8707 TypeStructField *it_field = type_entry->data.structure.fields[src_field_index_end];
8708 if (it_field->gen_index != type_struct_field->gen_index)
8709 break;
8710 }
8711
8712 if (src_field_index + 1 == src_field_index_end && !type_entry->data.structure.misaligned_field) {
8713 ZigValue *field_val = const_val->data.x_struct.fields[src_field_index];
8714 LLVMValueRef val = gen_const_val(g, field_val, "");
8715 fields[type_struct_field->gen_index] = val;
8716 make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_val->type, val);
8717 } else {
8718 bool is_big_endian = g->is_big_endian; // TODO get endianness from struct type
8719 LLVMTypeRef field_ty = LLVMStructGetTypeAtIndex(get_llvm_type(g, type_entry),
8720 (unsigned)type_struct_field->gen_index);
8721 const size_t size_in_bytes = LLVMStoreSizeOfType(g->target_data_ref, field_ty);
8722 const size_t size_in_bits = size_in_bytes * 8;
8723 LLVMTypeRef big_int_type_ref = LLVMIntType(size_in_bits);
8724 LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false);
8725 size_t used_bits = 0;
8726 for (size_t i = src_field_index; i < src_field_index_end; i += 1) {
8727 TypeStructField *it_field = type_entry->data.structure.fields[i];
8728 if (it_field->gen_index == SIZE_MAX) {
8729 continue;
8730 }
8731 LLVMValueRef child_val = pack_const_int(g, big_int_type_ref,
8732 const_val->data.x_struct.fields[i]);
8733 uint32_t packed_bits_size = type_size_bits(g, it_field->type_entry);
8734 if (is_big_endian) {
8735 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref,
8736 size_in_bits - used_bits - packed_bits_size, false);
8737 LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
8738 val = LLVMConstOr(val, child_val_shifted);
8739 } else {
8740 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false);
8741 LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
8742 val = LLVMConstOr(val, child_val_shifted);
8743 }
8744 used_bits += packed_bits_size;
8745 }
8746 assert(size_in_bits >= used_bits);
8747 if (LLVMGetTypeKind(field_ty) != LLVMArrayTypeKind) {
8748 assert(LLVMGetTypeKind(field_ty) == LLVMIntegerTypeKind);
8749 fields[type_struct_field->gen_index] = val;
8750 } else {
8751 const LLVMValueRef AMT = LLVMConstInt(LLVMTypeOf(val), 8, false);
8752
8753 LLVMValueRef *values = heap::c_allocator.allocate<LLVMValueRef>(size_in_bytes);
8754 for (size_t i = 0; i < size_in_bytes; i++) {
8755 const size_t idx = is_big_endian ? size_in_bytes - 1 - i : i;
8756 values[idx] = LLVMConstTruncOrBitCast(val, LLVMInt8Type());
8757 val = LLVMConstLShr(val, AMT);
8758 }
8759
8760 fields[type_struct_field->gen_index] = LLVMConstArray(LLVMInt8Type(), values, size_in_bytes);
8761 }
8762 }
8763
8764 src_field_index = src_field_index_end;
8765 }
8766 } else {
8767 for (uint32_t i = 0; i < src_field_count; i += 1) {
8768 TypeStructField *type_struct_field = type_entry->data.structure.fields[i];
8769 if (type_struct_field->gen_index == SIZE_MAX || type_struct_field->is_comptime) {
8770 continue;
8771 }
8772 ZigValue *field_val = const_val->data.x_struct.fields[i];
8773 if (field_val == nullptr) {
8774 add_node_error(g, type_struct_field->decl_node,
8775 buf_sprintf("compiler bug: generating const value for struct field '%s'",
8776 buf_ptr(type_struct_field->name)));
8777 codegen_report_errors_and_exit(g);
8778 }
8779 ZigType *field_type = field_val->type;
8780 assert(field_type != nullptr);
8781 if ((err = ensure_const_val_repr(nullptr, g, nullptr, field_val, field_type))) {
8782 zig_unreachable();
8783 }
8784
8785 LLVMValueRef val = gen_const_val(g, field_val, "");
8786 make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_type, val);
8787
8788 // Find the next runtime field
8789 size_t next_rt_gen_index = type_entry->data.structure.gen_field_count;
8790 size_t next_offset = type_entry->abi_size;
8791 for (size_t j = i + 1; j < src_field_count; j++) {
8792 const size_t index = type_entry->data.structure.fields[j]->gen_index;
8793 const size_t offset = type_entry->data.structure.fields[j]->offset;
8794
8795 if (index != SIZE_MAX) {
8796 next_rt_gen_index = index;
8797 next_offset = offset;
8798 break;
8799 }
8800 }
8801
8802 // How much padding is needed to reach the next field
8803 const size_t pad_bytes = next_offset -
8804 (type_struct_field->offset + LLVMABISizeOfType(g->target_data_ref, LLVMTypeOf(val)));
8805 // Catch underflow
8806 assert((ssize_t)pad_bytes >= 0);
8807
8808 if (type_struct_field->gen_index + 1 != next_rt_gen_index) {
8809 // If there's a hole between this field and the next
8810 // we have an alignment gap to fill
8811 fields[type_struct_field->gen_index] = val;
8812 fields[type_struct_field->gen_index + 1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_bytes));
8813 } else if (pad_bytes != 0) {
8814 LLVMValueRef padded_val[] = {
8815 val,
8816 LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_bytes)),
8817 };
8818 fields[type_struct_field->gen_index] = LLVMConstStruct(padded_val, 2, true);
8819 make_unnamed_struct = true;
8820 } else {
8821 fields[type_struct_field->gen_index] = val;
8822 }
8823 }
8824 }
8825 if (make_unnamed_struct) {
8826 LLVMValueRef unnamed_struct = LLVMConstStruct(fields, type_entry->data.structure.gen_field_count,
8827 type_entry->data.structure.layout == ContainerLayoutPacked);
8828 heap::c_allocator.deallocate(fields, type_entry->data.structure.gen_field_count);
8829 return unnamed_struct;
8830 } else {
8831 LLVMValueRef named_struct = LLVMConstNamedStruct(get_llvm_type(g, type_entry), fields, type_entry->data.structure.gen_field_count);
8832 heap::c_allocator.deallocate(fields, type_entry->data.structure.gen_field_count);
8833 return named_struct;
8834 }
8835 }
8836 case ZigTypeIdArray:
8837 {
8838 uint64_t len = type_entry->data.array.len;
8839 switch (const_val->data.x_array.special) {
8840 case ConstArraySpecialUndef:
8841 return LLVMGetUndef(get_llvm_type(g, type_entry));
8842 case ConstArraySpecialNone: {
8843 uint64_t extra_len_from_sentinel = (type_entry->data.array.sentinel != nullptr) ? 1 : 0;
8844 uint64_t full_len = len + extra_len_from_sentinel;
8845 LLVMValueRef *values = heap::c_allocator.allocate<LLVMValueRef>(full_len);
8846 LLVMTypeRef element_type_ref = get_llvm_type(g, type_entry->data.array.child_type);
8847 bool make_unnamed_struct = false;
8848 for (uint64_t i = 0; i < len; i += 1) {
8849 ZigValue *elem_value = &const_val->data.x_array.data.s_none.elements[i];
8850 LLVMValueRef val = gen_const_val(g, elem_value, "");
8851 values[i] = val;
8852 make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, elem_value->type, val);
8853 }
8854 if (type_entry->data.array.sentinel != nullptr) {
8855 values[len] = gen_const_val(g, type_entry->data.array.sentinel, "");
8856 }
8857 if (make_unnamed_struct) {
8858 LLVMValueRef unnamed_struct = LLVMConstStruct(values, full_len, true);
8859 heap::c_allocator.deallocate(values, full_len);
8860 return unnamed_struct;
8861 } else {
8862 LLVMValueRef array = LLVMConstArray(element_type_ref, values, (unsigned)full_len);
8863 heap::c_allocator.deallocate(values, full_len);
8864 return array;
8865 }
8866 }
8867 case ConstArraySpecialBuf: {
8868 Buf *buf = const_val->data.x_array.data.s_buf;
8869 return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf),
8870 type_entry->data.array.sentinel == nullptr);
8871 }
8872 }
8873 zig_unreachable();
8874 }
8875 case ZigTypeIdVector: {
8876 uint32_t len = type_entry->data.vector.len;
8877 switch (const_val->data.x_array.special) {
8878 case ConstArraySpecialUndef:
8879 return LLVMGetUndef(get_llvm_type(g, type_entry));
8880 case ConstArraySpecialNone: {
8881 LLVMValueRef *values = heap::c_allocator.allocate<LLVMValueRef>(len);
8882 for (uint64_t i = 0; i < len; i += 1) {
8883 ZigValue *elem_value = &const_val->data.x_array.data.s_none.elements[i];
8884 values[i] = gen_const_val(g, elem_value, "");
8885 }
8886 LLVMValueRef vector = LLVMConstVector(values, len);
8887 heap::c_allocator.deallocate(values, len);
8888 return vector;
8889 }
8890 case ConstArraySpecialBuf: {
8891 Buf *buf = const_val->data.x_array.data.s_buf;
8892 assert(buf_len(buf) == len);
8893 LLVMValueRef *values = heap::c_allocator.allocate<LLVMValueRef>(len);
8894 for (uint64_t i = 0; i < len; i += 1) {
8895 values[i] = LLVMConstInt(g->builtin_types.entry_u8->llvm_type, buf_ptr(buf)[i], false);
8896 }
8897 LLVMValueRef vector = LLVMConstVector(values, len);
8898 heap::c_allocator.deallocate(values, len);
8899 return vector;
8900 }
8901 }
8902 zig_unreachable();
8903 }
8904 case ZigTypeIdUnion:
8905 {
8906 // Force type_entry->data.unionation.union_llvm_type to get resolved
8907 (void)get_llvm_type(g, type_entry);
8908
8909 if (type_entry->data.unionation.gen_field_count == 0) {
8910 if (type_entry->data.unionation.tag_type == nullptr) {
8911 return nullptr;
8912 } else {
8913 return bigint_to_llvm_const(get_llvm_type(g, type_entry->data.unionation.tag_type),
8914 &const_val->data.x_union.tag);
8915 }
8916 }
8917
8918 LLVMTypeRef union_type_ref = type_entry->data.unionation.union_llvm_type;
8919 assert(union_type_ref != nullptr);
8920
8921 LLVMValueRef union_value_ref;
8922 bool make_unnamed_struct;
8923 ZigValue *payload_value = const_val->data.x_union.payload;
8924 if (payload_value == nullptr || !type_has_bits(g, payload_value->type)) {
8925 if (type_entry->data.unionation.gen_tag_index == SIZE_MAX)
8926 return LLVMGetUndef(get_llvm_type(g, type_entry));
8927
8928 union_value_ref = LLVMGetUndef(union_type_ref);
8929 make_unnamed_struct = false;
8930 } else {
8931 uint64_t field_type_bytes = LLVMABISizeOfType(g->target_data_ref,
8932 get_llvm_type(g, payload_value->type));
8933 uint64_t pad_bytes = type_entry->data.unionation.union_abi_size - field_type_bytes;
8934 LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value, "");
8935 make_unnamed_struct = is_llvm_value_unnamed_type(g, payload_value->type, correctly_typed_value) ||
8936 payload_value->type != type_entry->data.unionation.most_aligned_union_member->type_entry;
8937
8938 {
8939 if (pad_bytes == 0) {
8940 union_value_ref = correctly_typed_value;
8941 } else {
8942 LLVMValueRef fields[2];
8943 fields[0] = correctly_typed_value;
8944 fields[1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes));
8945 if (make_unnamed_struct || type_entry->data.unionation.gen_tag_index != SIZE_MAX) {
8946 union_value_ref = LLVMConstStruct(fields, 2, false);
8947 } else {
8948 union_value_ref = LLVMConstNamedStruct(union_type_ref, fields, 2);
8949 }
8950 }
8951 }
8952
8953 if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) {
8954 return union_value_ref;
8955 }
8956 }
8957
8958 LLVMValueRef tag_value = bigint_to_llvm_const(
8959 get_llvm_type(g, type_entry->data.unionation.tag_type),
8960 &const_val->data.x_union.tag);
8961
8962 LLVMValueRef fields[3];
8963 fields[type_entry->data.unionation.gen_union_index] = union_value_ref;
8964 fields[type_entry->data.unionation.gen_tag_index] = tag_value;
8965
8966 if (make_unnamed_struct) {
8967 LLVMValueRef result = LLVMConstStruct(fields, 2, false);
8968 uint64_t last_field_offset = LLVMOffsetOfElement(g->target_data_ref, LLVMTypeOf(result), 1);
8969 uint64_t end_offset = last_field_offset +
8970 LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(fields[1]));
8971 uint64_t expected_sz = LLVMABISizeOfType(g->target_data_ref, get_llvm_type(g, type_entry));
8972 unsigned pad_sz = expected_sz - end_offset;
8973 if (pad_sz != 0) {
8974 fields[2] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz));
8975 result = LLVMConstStruct(fields, 3, false);
8976 }
8977 uint64_t actual_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(result));
8978 assert(actual_sz == expected_sz);
8979 return result;
8980 } else {
8981 return LLVMConstNamedStruct(get_llvm_type(g, type_entry), fields, 2);
8982 }
8983
8984 }
8985
8986 case ZigTypeIdEnum:
8987 return bigint_to_llvm_const(get_llvm_type(g, type_entry), &const_val->data.x_enum_tag);
8988 case ZigTypeIdFn:
8989 if (const_val->data.x_ptr.special == ConstPtrSpecialFunction &&
8990 const_val->data.x_ptr.mut != ConstPtrMutComptimeConst) {
8991 zig_unreachable();
8992 }
8993 // Treat it the same as we do for pointers
8994 return gen_const_val_ptr(g, const_val, name);
8995 case ZigTypeIdPointer:
8996 return gen_const_val_ptr(g, const_val, name);
8997 case ZigTypeIdErrorUnion:
8998 {
8999 ZigType *payload_type = type_entry->data.error_union.payload_type;
9000 ZigType *err_set_type = type_entry->data.error_union.err_set_type;
9001 if (!type_has_bits(g, payload_type)) {
9002 assert(type_has_bits(g, err_set_type));
9003 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
9004 uint64_t value = (err_set == nullptr) ? 0 : err_set->value;
9005 return LLVMConstInt(get_llvm_type(g, g->err_tag_type), value, false);
9006 } else if (!type_has_bits(g, err_set_type)) {
9007 assert(type_has_bits(g, payload_type));
9008 return gen_const_val(g, const_val->data.x_err_union.payload, "");
9009 } else {
9010 LLVMValueRef err_tag_value;
9011 LLVMValueRef err_payload_value;
9012 bool make_unnamed_struct;
9013 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
9014 if (err_set != nullptr) {
9015 err_tag_value = LLVMConstInt(get_llvm_type(g, g->err_tag_type), err_set->value, false);
9016 err_payload_value = LLVMConstNull(get_llvm_type(g, payload_type));
9017 make_unnamed_struct = false;
9018 } else {
9019 err_tag_value = LLVMConstNull(get_llvm_type(g, g->err_tag_type));
9020 ZigValue *payload_val = const_val->data.x_err_union.payload;
9021 err_payload_value = gen_const_val(g, payload_val, "");
9022 make_unnamed_struct = is_llvm_value_unnamed_type(g, payload_val->type, err_payload_value);
9023 }
9024 LLVMValueRef fields[3];
9025 fields[err_union_err_index] = err_tag_value;
9026 fields[err_union_payload_index] = err_payload_value;
9027 size_t field_count = 2;
9028 if (type_entry->data.error_union.pad_llvm_type != nullptr) {
9029 fields[2] = LLVMGetUndef(type_entry->data.error_union.pad_llvm_type);
9030 field_count = 3;
9031 }
9032 if (make_unnamed_struct) {
9033 return LLVMConstStruct(fields, field_count, false);
9034 } else {
9035 return LLVMConstNamedStruct(get_llvm_type(g, type_entry), fields, field_count);
9036 }
9037 }
9038 }
9039 case ZigTypeIdVoid:
9040 return nullptr;
9041 case ZigTypeIdInvalid:
9042 case ZigTypeIdMetaType:
9043 case ZigTypeIdUnreachable:
9044 case ZigTypeIdComptimeFloat:
9045 case ZigTypeIdComptimeInt:
9046 case ZigTypeIdEnumLiteral:
9047 case ZigTypeIdUndefined:
9048 case ZigTypeIdNull:
9049 case ZigTypeIdBoundFn:
9050 case ZigTypeIdOpaque:
9051 zig_unreachable();
9052 case ZigTypeIdFnFrame:
9053 zig_panic("TODO: gen_const_val ZigTypeIdFnFrame");
9054 case ZigTypeIdAnyFrame:
9055 zig_panic("TODO: gen_const_val ZigTypeIdAnyFrame");
9056 }
9057 zig_unreachable();
9058}
9059
9060static void render_const_val(CodeGen *g, ZigValue *const_val, const char *name) {
9061 if (!const_val->llvm_value)
9062 const_val->llvm_value = gen_const_val(g, const_val, name);
9063
9064 if (const_val->llvm_global)
9065 LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
9066}
9067
9068static void render_const_val_global(CodeGen *g, ZigValue *const_val, const char *name) {
9069 if (!const_val->llvm_global) {
9070 LLVMTypeRef type_ref = const_val->llvm_value ?
9071 LLVMTypeOf(const_val->llvm_value) : get_llvm_type(g, const_val->type);
9072 LLVMValueRef global_value = LLVMAddGlobal(g->module, type_ref, name);
9073 LLVMSetLinkage(global_value, (name == nullptr) ? LLVMPrivateLinkage : LLVMInternalLinkage);
9074 LLVMSetGlobalConstant(global_value, true);
9075 LLVMSetUnnamedAddr(global_value, true);
9076 LLVMSetAlignment(global_value, (const_val->llvm_align == 0) ?
9077 get_abi_alignment(g, const_val->type) : const_val->llvm_align);
9078
9079 const_val->llvm_global = global_value;
9080 }
9081
9082 if (const_val->llvm_value)
9083 LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
9084}
9085
9086static void generate_error_name_table(CodeGen *g) {
9087 if (g->err_name_table != nullptr || !g->generate_error_name_table) {
9088 return;
9089 }
9090
9091 assert(g->errors_by_index.length > 0);
9092
9093 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
9094 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false);
9095 ZigType *str_type = get_slice_type(g, u8_ptr_type);
9096
9097 LLVMValueRef *values = heap::c_allocator.allocate<LLVMValueRef>(g->errors_by_index.length);
9098 values[0] = LLVMGetUndef(get_llvm_type(g, str_type));
9099 for (size_t i = 1; i < g->errors_by_index.length; i += 1) {
9100 ErrorTableEntry *err_entry = g->errors_by_index.at(i);
9101 Buf *name = &err_entry->name;
9102
9103 g->largest_err_name_len = max(g->largest_err_name_len, buf_len(name));
9104
9105 LLVMValueRef str_init = LLVMConstString(buf_ptr(name), (unsigned)buf_len(name), false);
9106 LLVMValueRef str_global = LLVMAddGlobal(g->module, LLVMTypeOf(str_init), "");
9107 LLVMSetInitializer(str_global, str_init);
9108 LLVMSetLinkage(str_global, LLVMPrivateLinkage);
9109 LLVMSetGlobalConstant(str_global, true);
9110 LLVMSetUnnamedAddr(str_global, true);
9111 LLVMSetAlignment(str_global, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(str_init)));
9112
9113 LLVMValueRef fields[] = {
9114 LLVMConstBitCast(str_global, get_llvm_type(g, u8_ptr_type)),
9115 LLVMConstInt(g->builtin_types.entry_usize->llvm_type, buf_len(name), false),
9116 };
9117 values[i] = LLVMConstNamedStruct(get_llvm_type(g, str_type), fields, 2);
9118 }
9119
9120 LLVMValueRef err_name_table_init = LLVMConstArray(get_llvm_type(g, str_type), values, (unsigned)g->errors_by_index.length);
9121 heap::c_allocator.deallocate(values, g->errors_by_index.length);
9122
9123 g->err_name_table = LLVMAddGlobal(g->module, LLVMTypeOf(err_name_table_init),
9124 get_mangled_name(g, buf_ptr(buf_create_from_str("__zig_err_name_table"))));
9125 LLVMSetInitializer(g->err_name_table, err_name_table_init);
9126 LLVMSetLinkage(g->err_name_table, LLVMPrivateLinkage);
9127 LLVMSetGlobalConstant(g->err_name_table, true);
9128 LLVMSetUnnamedAddr(g->err_name_table, true);
9129 LLVMSetAlignment(g->err_name_table, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(err_name_table_init)));
9130}
9131
9132static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) {
9133 Stage1Air *executable = &fn->analyzed_executable;
9134 assert(executable->basic_block_list.length > 0);
9135 LLVMValueRef fn_val = fn_llvm_value(g, fn);
9136 LLVMBasicBlockRef first_bb = nullptr;
9137 if (fn_is_async(fn)) {
9138 first_bb = LLVMAppendBasicBlock(fn_val, "AsyncSwitch");
9139 g->cur_preamble_llvm_block = first_bb;
9140 }
9141 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
9142 Stage1AirBasicBlock *bb = executable->basic_block_list.at(block_i);
9143 bb->llvm_block = LLVMAppendBasicBlock(fn_val, bb->name_hint);
9144 }
9145 if (first_bb == nullptr) {
9146 first_bb = executable->basic_block_list.at(0)->llvm_block;
9147 }
9148 LLVMPositionBuilderAtEnd(g->builder, first_bb);
9149}
9150
9151static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val,
9152 ZigType *type_entry)
9153{
9154 if (g->strip_debug_symbols) {
9155 return;
9156 }
9157
9158 assert(var->gen_is_const);
9159 assert(type_entry);
9160
9161 ZigType *import = get_scope_import(var->parent_scope);
9162 assert(import);
9163
9164 bool is_local_to_unit = true;
9165 ZigLLVMCreateGlobalVariable(g->dbuilder, get_di_scope(g, var->parent_scope), var->name,
9166 var->name, import->data.structure.root_struct->di_file,
9167 node_line_onebased(var->decl_node),
9168 get_llvm_di_type(g, type_entry), is_local_to_unit);
9169
9170 // TODO ^^ make an actual global variable
9171}
9172
9173static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
9174 bool is_extern = var->decl_node->data.variable_declaration.is_extern;
9175 bool is_export = var->decl_node->data.variable_declaration.is_export;
9176 bool is_internal_linkage = !is_extern && !is_export;
9177 if (var->is_thread_local && (!g->is_single_threaded || !is_internal_linkage)) {
9178 LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
9179 }
9180}
9181
9182static void do_code_gen(CodeGen *g) {
9183 Error err;
9184 assert(!g->errors.length);
9185
9186 generate_error_name_table(g);
9187
9188 // Generate module level variables
9189 for (size_t i = 0; i < g->global_vars.length; i += 1) {
9190 TldVar *tld_var = g->global_vars.at(i);
9191 ZigVar *var = tld_var->var;
9192
9193 if (var->var_type->id == ZigTypeIdComptimeFloat) {
9194 // Generate debug info for it but that's it.
9195 ZigValue *const_val = var->const_value;
9196 assert(const_val->special != ConstValSpecialRuntime);
9197 if ((err = ir_resolve_lazy(g, var->decl_node, const_val)))
9198 zig_unreachable();
9199 if (const_val->type != var->var_type) {
9200 zig_panic("TODO debug info for var with ptr casted value");
9201 }
9202 ZigType *var_type = g->builtin_types.entry_f128;
9203 ZigValue coerced_value = {};
9204 coerced_value.special = ConstValSpecialStatic;
9205 coerced_value.type = var_type;
9206 coerced_value.data.x_f128 = bigfloat_to_f128(&const_val->data.x_bigfloat);
9207 LLVMValueRef init_val = gen_const_val(g, &coerced_value, "");
9208 gen_global_var(g, var, init_val, var_type);
9209 continue;
9210 }
9211
9212 if (var->var_type->id == ZigTypeIdComptimeInt) {
9213 // Generate debug info for it but that's it.
9214 ZigValue *const_val = var->const_value;
9215 assert(const_val->special != ConstValSpecialRuntime);
9216 if ((err = ir_resolve_lazy(g, var->decl_node, const_val)))
9217 zig_unreachable();
9218 if (const_val->type != var->var_type) {
9219 zig_panic("TODO debug info for var with ptr casted value");
9220 }
9221 size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);
9222 if (bits_needed < 8) {
9223 bits_needed = 8;
9224 }
9225 ZigType *var_type = get_int_type(g, const_val->data.x_bigint.is_negative, bits_needed);
9226 LLVMValueRef init_val = bigint_to_llvm_const(get_llvm_type(g, var_type), &const_val->data.x_bigint);
9227 gen_global_var(g, var, init_val, var_type);
9228 continue;
9229 }
9230
9231 if (!type_has_bits(g, var->var_type))
9232 continue;
9233
9234 assert(var->decl_node);
9235
9236 GlobalLinkageId linkage;
9237 const char *unmangled_name = var->name;
9238 const char *symbol_name;
9239 if (var->export_list.length == 0) {
9240 if (var->decl_node->data.variable_declaration.is_extern) {
9241 symbol_name = unmangled_name;
9242 linkage = GlobalLinkageIdStrong;
9243 } else {
9244 symbol_name = get_mangled_name(g, unmangled_name);
9245 linkage = GlobalLinkageIdInternal;
9246 }
9247 } else {
9248 GlobalExport *global_export = &var->export_list.items[0];
9249 symbol_name = buf_ptr(&global_export->name);
9250 linkage = global_export->linkage;
9251 }
9252
9253 LLVMValueRef global_value;
9254 bool externally_initialized = var->decl_node->data.variable_declaration.expr == nullptr;
9255 if (externally_initialized) {
9256 LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, symbol_name);
9257 if (existing_llvm_var) {
9258 global_value = LLVMConstBitCast(existing_llvm_var,
9259 LLVMPointerType(get_llvm_type(g, var->var_type), 0));
9260 } else {
9261 global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), symbol_name);
9262 // TODO debug info for the extern variable
9263
9264 LLVMSetLinkage(global_value, to_llvm_linkage(linkage, true));
9265 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
9266 LLVMSetAlignment(global_value, var->align_bytes);
9267 LLVMSetGlobalConstant(global_value, var->gen_is_const);
9268 set_global_tls(g, var, global_value);
9269 }
9270 } else {
9271 bool exported = (linkage != GlobalLinkageIdInternal);
9272 render_const_val(g, var->const_value, symbol_name);
9273 render_const_val_global(g, var->const_value, symbol_name);
9274 global_value = var->const_value->llvm_global;
9275
9276 if (exported) {
9277 LLVMSetLinkage(global_value, to_llvm_linkage(linkage, false));
9278 maybe_export_dll(g, global_value, GlobalLinkageIdStrong);
9279 }
9280 if (var->section_name) {
9281 LLVMSetSection(global_value, buf_ptr(var->section_name));
9282 }
9283 LLVMSetAlignment(global_value, var->align_bytes);
9284
9285 // TODO debug info for function pointers
9286 // Here we use const_value->type because that's the type of the llvm global,
9287 // which we const ptr cast upon use to whatever it needs to be.
9288 if (var->gen_is_const && var->const_value->type->id != ZigTypeIdFn) {
9289 gen_global_var(g, var, var->const_value->llvm_value, var->const_value->type);
9290 }
9291
9292 LLVMSetGlobalConstant(global_value, var->gen_is_const);
9293 set_global_tls(g, var, global_value);
9294 }
9295
9296 var->value_ref = global_value;
9297
9298 for (size_t export_i = 1; export_i < var->export_list.length; export_i += 1) {
9299 GlobalExport *global_export = &var->export_list.items[export_i];
9300 LLVMAddAlias2(g->module, LLVMTypeOf(var->value_ref), 0, var->value_ref, buf_ptr(&global_export->name));
9301 }
9302 }
9303
9304 // Generate function definitions.
9305 stage2_progress_update_node(g->sub_progress_node, 0, g->fn_defs.length);
9306 for (size_t fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) {
9307 ZigFn *fn_table_entry = g->fn_defs.at(fn_i);
9308 Stage2ProgressNode *fn_prog_node = stage2_progress_start(g->sub_progress_node,
9309 buf_ptr(&fn_table_entry->symbol_name), buf_len(&fn_table_entry->symbol_name), 0);
9310
9311 FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id;
9312 CallingConvention cc = fn_type_id->cc;
9313 bool is_c_abi = !calling_convention_allows_zig_types(cc);
9314 bool want_sret = want_first_arg_sret(g, fn_type_id);
9315
9316 LLVMValueRef fn = fn_llvm_value(g, fn_table_entry);
9317 g->cur_fn = fn_table_entry;
9318 g->cur_fn_val = fn;
9319
9320 build_all_basic_blocks(g, fn_table_entry);
9321 clear_debug_source_node(g);
9322
9323 bool is_async = fn_is_async(fn_table_entry);
9324
9325 if (is_async) {
9326 g->cur_frame_ptr = LLVMGetParam(fn, 0);
9327 } else {
9328 if (want_sret) {
9329 g->cur_ret_ptr = LLVMGetParam(fn, 0);
9330 } else if (type_has_bits(g, fn_type_id->return_type)) {
9331 g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0);
9332 // TODO add debug info variable for this
9333 } else {
9334 g->cur_ret_ptr = nullptr;
9335 }
9336 }
9337
9338 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
9339 bool have_err_ret_trace_arg = err_ret_trace_arg_index != UINT32_MAX;
9340 if (have_err_ret_trace_arg) {
9341 g->cur_err_ret_trace_val_arg = LLVMGetParam(fn, err_ret_trace_arg_index);
9342 } else {
9343 g->cur_err_ret_trace_val_arg = nullptr;
9344 }
9345
9346 // error return tracing setup
9347 bool have_err_ret_trace_stack = g->have_err_ret_tracing && fn_table_entry->calls_or_awaits_errorable_fn &&
9348 !is_async && !have_err_ret_trace_arg;
9349 LLVMValueRef err_ret_array_val = nullptr;
9350 if (have_err_ret_trace_stack) {
9351 ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, nullptr);
9352 err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", get_abi_alignment(g, array_type));
9353
9354 (void)get_llvm_type(g, get_stack_trace_type(g));
9355 g->cur_err_ret_trace_val_stack = build_alloca(g, get_stack_trace_type(g), "error_return_trace",
9356 get_abi_alignment(g, g->stack_trace_type));
9357 } else {
9358 g->cur_err_ret_trace_val_stack = nullptr;
9359 }
9360
9361 if (fn_returns_c_abi_small_struct(fn_type_id)) {
9362 LLVMTypeRef abi_type = get_llvm_c_abi_type(g, fn_type_id->return_type);
9363 fn_table_entry->abi_return_value = LLVMBuildAlloca(g->builder, abi_type, "");
9364 }
9365
9366 if (!is_async) {
9367 // allocate async frames for nosuspend calls & awaits to async functions
9368 ZigType *largest_call_frame_type = nullptr;
9369 Stage1AirInst *all_calls_alloca = ir_create_alloca(g, &fn_table_entry->fndef_scope->base,
9370 fn_table_entry->body_node, fn_table_entry, g->builtin_types.entry_void, "@async_call_frame");
9371 for (size_t i = 0; i < fn_table_entry->call_list.length; i += 1) {
9372 Stage1AirInstCall *call = fn_table_entry->call_list.at(i);
9373 if (call->fn_entry == nullptr)
9374 continue;
9375 if (!fn_is_async(call->fn_entry))
9376 continue;
9377 if (call->modifier != CallModifierNoSuspend)
9378 continue;
9379 if (call->frame_result_loc != nullptr)
9380 continue;
9381 ZigType *callee_frame_type = get_fn_frame_type(g, call->fn_entry);
9382 if (largest_call_frame_type == nullptr ||
9383 callee_frame_type->abi_size > largest_call_frame_type->abi_size)
9384 {
9385 largest_call_frame_type = callee_frame_type;
9386 }
9387 call->frame_result_loc = all_calls_alloca;
9388 }
9389 if (largest_call_frame_type != nullptr) {
9390 all_calls_alloca->value->type = get_pointer_to_type(g, largest_call_frame_type, false);
9391 }
9392 // allocate temporary stack data
9393 for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) {
9394 Stage1AirInstAlloca *instruction = fn_table_entry->alloca_gen_list.at(alloca_i);
9395 ZigType *ptr_type = instruction->base.value->type;
9396 assert(ptr_type->id == ZigTypeIdPointer);
9397 ZigType *child_type = ptr_type->data.pointer.child_type;
9398 if (type_resolve(g, child_type, ResolveStatusSizeKnown))
9399 zig_unreachable();
9400 if (!type_has_bits(g, child_type))
9401 continue;
9402 if (instruction->base.ref_count == 0)
9403 continue;
9404 if (instruction->base.value->special != ConstValSpecialRuntime) {
9405 if (const_ptr_pointee(nullptr, g, instruction->base.value, nullptr)->special !=
9406 ConstValSpecialRuntime)
9407 {
9408 continue;
9409 }
9410 }
9411 if (type_resolve(g, child_type, ResolveStatusLLVMFull))
9412 zig_unreachable();
9413 instruction->base.llvm_value = build_alloca(g, child_type, instruction->name_hint,
9414 get_ptr_align(g, ptr_type));
9415 }
9416 }
9417
9418 ZigType *import = get_scope_import(&fn_table_entry->fndef_scope->base);
9419 unsigned gen_i_init = want_sret ? 1 : 0;
9420
9421 // create debug variable declarations for variables and allocate all local variables
9422 FnWalk fn_walk_var = {};
9423 fn_walk_var.id = FnWalkIdVars;
9424 fn_walk_var.data.vars.import = import;
9425 fn_walk_var.data.vars.fn = fn_table_entry;
9426 fn_walk_var.data.vars.llvm_fn = fn;
9427 fn_walk_var.data.vars.gen_i = gen_i_init;
9428 for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
9429 ZigVar *var = fn_table_entry->variable_list.at(var_i);
9430
9431 if (!type_has_bits(g, var->var_type)) {
9432 continue;
9433 }
9434 if (ir_get_var_is_comptime(var))
9435 continue;
9436 switch (type_requires_comptime(g, var->var_type)) {
9437 case ReqCompTimeInvalid:
9438 zig_unreachable();
9439 case ReqCompTimeYes:
9440 continue;
9441 case ReqCompTimeNo:
9442 break;
9443 }
9444
9445 if (var->src_arg_index == SIZE_MAX) {
9446 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
9447 var->name, import->data.structure.root_struct->di_file,
9448 node_line_onebased(var->decl_node),
9449 get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0);
9450
9451 } else if (is_c_abi) {
9452 fn_walk_var.data.vars.var = var;
9453 iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk_var, var->src_arg_index);
9454 } else if (!is_async) {
9455 ZigType *gen_type;
9456 FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];
9457 assert(gen_info->gen_index != SIZE_MAX);
9458
9459 if (handle_is_ptr(g, var->var_type)) {
9460 if (gen_info->is_byval) {
9461 gen_type = var->var_type;
9462 } else {
9463 gen_type = gen_info->type;
9464 }
9465 var->value_ref = LLVMGetParam(fn, gen_info->gen_index);
9466 } else {
9467 gen_type = var->var_type;
9468 var->value_ref = build_alloca(g, var->var_type, var->name, var->align_bytes);
9469 }
9470 if (var->decl_node) {
9471 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
9472 var->name, import->data.structure.root_struct->di_file,
9473 node_line_onebased(var->decl_node),
9474 get_llvm_di_type(g, gen_type), !g->strip_debug_symbols, 0, (unsigned)(gen_info->gen_index+1));
9475 }
9476
9477 }
9478 }
9479
9480 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
9481
9482 // finishing error return trace setup. we have to do this after all the allocas.
9483 if (have_err_ret_trace_stack) {
9484 ZigType *usize = g->builtin_types.entry_usize;
9485 size_t index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index;
9486 LLVMValueRef index_field_ptr = LLVMBuildStructGEP2(g->builder,
9487 get_llvm_type(g, g->stack_trace_type),
9488 g->cur_err_ret_trace_val_stack, (unsigned)index_field_index, "");
9489 gen_store_untyped(g, LLVMConstNull(usize->llvm_type), index_field_ptr, 0, false);
9490
9491 size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index;
9492 LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP2(g->builder,
9493 get_llvm_type(g, g->stack_trace_type),
9494 g->cur_err_ret_trace_val_stack, (unsigned)addresses_field_index, "");
9495
9496 ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry;
9497 size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index;
9498 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder,
9499 ZigLLVMGetGEPResultElementType(addresses_field_ptr),
9500 addresses_field_ptr, (unsigned)ptr_field_index, "");
9501 LLVMValueRef zero = LLVMConstNull(usize->llvm_type);
9502 LLVMValueRef indices[] = {zero, zero};
9503 LLVMValueRef err_ret_array_val_elem0_ptr = LLVMBuildInBoundsGEP2(g->builder,
9504 LLVMGetAllocatedType(err_ret_array_val), err_ret_array_val, indices, 2, "");
9505 ZigType *ptr_ptr_usize_type = get_pointer_to_type(g, get_pointer_to_type(g, usize, false), false);
9506 gen_store(g, err_ret_array_val_elem0_ptr, ptr_field_ptr, ptr_ptr_usize_type);
9507
9508 size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index;
9509 LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder,
9510 ZigLLVMGetGEPResultElementType(addresses_field_ptr),
9511 addresses_field_ptr, (unsigned)len_field_index, "");
9512 gen_store(g, LLVMConstInt(usize->llvm_type, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false));
9513 }
9514
9515 if (is_async) {
9516 (void)get_llvm_type(g, fn_table_entry->frame_type);
9517 g->cur_resume_block_count = 0;
9518
9519 LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false);
9520 if (g->need_frame_size_prefix_data) {
9521 ZigLLVMFunctionSetPrefixData(fn_table_entry->llvm_value, size_val);
9522 }
9523
9524 if (!g->strip_debug_symbols) {
9525 AstNode *source_node = fn_table_entry->proto_node;
9526 ZigLLVMSetCurrentDebugLocation(g->builder,
9527 node_line_onebased(source_node), node_column_onebased(source_node),
9528 get_di_scope(g, fn_table_entry->child_scope));
9529 }
9530 Stage1Air *executable = &fn_table_entry->analyzed_executable;
9531 LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume");
9532 LLVMPositionBuilderAtEnd(g->builder, bad_resume_block);
9533 gen_assertion_scope(g, PanicMsgIdBadResume, fn_table_entry->child_scope);
9534
9535 LLVMPositionBuilderAtEnd(g->builder, g->cur_preamble_llvm_block);
9536 render_async_spills(g);
9537 g->cur_async_awaiter_ptr = LLVMBuildStructGEP2(g->builder,
9538 get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)),
9539 g->cur_frame_ptr, frame_awaiter_index, "");
9540 LLVMValueRef resume_index_ptr = LLVMBuildStructGEP2(g->builder,
9541 get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)),
9542 g->cur_frame_ptr, frame_resume_index, "");
9543 g->cur_async_resume_index_ptr = resume_index_ptr;
9544
9545 if (type_has_bits(g, fn_type_id->return_type)) {
9546 LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP2(g->builder,
9547 get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)),
9548 g->cur_frame_ptr, frame_ret_start, "");
9549 g->cur_ret_ptr = LLVMBuildLoad2(g->builder,
9550 ZigLLVMGetGEPResultElementType(cur_ret_ptr_ptr), cur_ret_ptr_ptr, "");
9551 }
9552 uint32_t trace_field_index_stack = UINT32_MAX;
9553 if (codegen_fn_has_err_ret_tracing_stack(g, fn_table_entry, true)) {
9554 trace_field_index_stack = frame_index_trace_stack(g, fn_table_entry);
9555 g->cur_err_ret_trace_val_stack = LLVMBuildStructGEP2(g->builder,
9556 get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)),
9557 g->cur_frame_ptr,
9558 trace_field_index_stack, "");
9559 }
9560
9561 LLVMValueRef resume_index = LLVMBuildLoad2(g->builder, usize_type_ref, resume_index_ptr, "");
9562 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4);
9563 g->cur_async_switch_instr = switch_instr;
9564
9565 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
9566 Stage1AirBasicBlock *entry_block = executable->basic_block_list.at(0);
9567 LLVMAddCase(switch_instr, zero, entry_block->llvm_block);
9568 g->cur_resume_block_count += 1;
9569
9570 {
9571 LLVMBasicBlockRef bad_not_suspended_bb = LLVMAppendBasicBlock(g->cur_fn_val, "NotSuspended");
9572 size_t new_block_index = g->cur_resume_block_count;
9573 g->cur_resume_block_count += 1;
9574 g->cur_bad_not_suspended_index = LLVMConstInt(usize_type_ref, new_block_index, false);
9575 LLVMAddCase(g->cur_async_switch_instr, g->cur_bad_not_suspended_index, bad_not_suspended_bb);
9576
9577 LLVMPositionBuilderAtEnd(g->builder, bad_not_suspended_bb);
9578 gen_assertion_scope(g, PanicMsgIdResumeNotSuspendedFn, fn_table_entry->child_scope);
9579 }
9580
9581 LLVMPositionBuilderAtEnd(g->builder, entry_block->llvm_block);
9582 LLVMBuildStore(g->builder, g->cur_bad_not_suspended_index, g->cur_async_resume_index_ptr);
9583 if (trace_field_index_stack != UINT32_MAX) {
9584 if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) {
9585 LLVMValueRef trace_ptr_ptr = LLVMBuildStructGEP2(g->builder,
9586 get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)),
9587 g->cur_frame_ptr,
9588 frame_index_trace_arg(g, fn_type_id->return_type), "");
9589 LLVMValueRef zero_ptr = LLVMConstNull(ZigLLVMGetGEPResultElementType(trace_ptr_ptr));
9590 LLVMBuildStore(g->builder, zero_ptr, trace_ptr_ptr);
9591 }
9592
9593 LLVMValueRef trace_field_ptr = LLVMBuildStructGEP2(g->builder,
9594 get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)),
9595 g->cur_frame_ptr,
9596 trace_field_index_stack, "");
9597 LLVMValueRef addrs_field_ptr = LLVMBuildStructGEP2(g->builder,
9598 get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)),
9599 g->cur_frame_ptr,
9600 trace_field_index_stack + 1, "");
9601
9602 gen_init_stack_trace(g, trace_field_ptr, addrs_field_ptr);
9603 }
9604 render_async_var_decls(g, entry_block->instruction_list.at(0)->scope);
9605 } else {
9606 // create debug variable declarations for parameters
9607 // rely on the first variables in the variable_list being parameters.
9608 FnWalk fn_walk_init = {};
9609 fn_walk_init.id = FnWalkIdInits;
9610 fn_walk_init.data.inits.fn = fn_table_entry;
9611 fn_walk_init.data.inits.llvm_fn = fn;
9612 fn_walk_init.data.inits.gen_i = gen_i_init;
9613 walk_function_params(g, fn_table_entry->type_entry, &fn_walk_init);
9614 }
9615
9616 ir_render(g, fn_table_entry);
9617
9618 stage2_progress_end(fn_prog_node);
9619 }
9620
9621 assert(!g->errors.length);
9622
9623 if (buf_len(&g->global_asm) != 0) {
9624 LLVMSetModuleInlineAsm2(g->module, buf_ptr(&g->global_asm), buf_len(&g->global_asm));
9625 }
9626
9627 while (g->type_resolve_stack.length != 0) {
9628 ZigType *ty = g->type_resolve_stack.last();
9629 if (type_resolve(g, ty, ResolveStatusLLVMFull))
9630 zig_unreachable();
9631 }
9632
9633 ZigLLVMDIBuilderFinalize(g->dbuilder);
9634
9635 if (g->verbose_llvm_ir) {
9636 fflush(stderr);
9637 LLVMDumpModule(g->module);
9638 }
9639
9640 char *error = nullptr;
9641 if (LLVMVerifyModule(g->module, LLVMReturnStatusAction, &error)) {
9642 zig_panic("broken LLVM module found: %s\nThis is a bug in the Zig compiler.", error);
9643 }
9644}
9645
9646static void zig_llvm_emit_output(CodeGen *g) {
9647 g->pass1_arena->destruct(&heap::c_allocator);
9648 g->pass1_arena = nullptr;
9649
9650 bool is_small = g->build_mode == BuildModeSmallRelease;
9651
9652 char *err_msg = nullptr;
9653 const char *asm_filename = nullptr;
9654 const char *bin_filename = nullptr;
9655 const char *llvm_ir_filename = nullptr;
9656 const char *bitcode_filename = nullptr;
9657
9658 if (buf_len(&g->o_file_output_path) != 0) bin_filename = buf_ptr(&g->o_file_output_path);
9659 if (buf_len(&g->asm_file_output_path) != 0) asm_filename = buf_ptr(&g->asm_file_output_path);
9660 if (buf_len(&g->llvm_ir_file_output_path) != 0) llvm_ir_filename = buf_ptr(&g->llvm_ir_file_output_path);
9661 if (buf_len(&g->bitcode_file_output_path) != 0) bitcode_filename = buf_ptr(&g->bitcode_file_output_path);
9662
9663 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.
9664 // So we call the entire pipeline multiple times if this is requested.
9665 if (asm_filename != nullptr && bin_filename != nullptr) {
9666 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg,
9667 g->build_mode == BuildModeDebug, is_small, g->enable_time_report, g->tsan_enabled,
9668 g->have_lto, nullptr, bin_filename, llvm_ir_filename, nullptr))
9669 {
9670 fprintf(stderr, "LLVM failed to emit bin=%s, ir=%s: %s\n",
9671 bin_filename, llvm_ir_filename, err_msg);
9672 exit(1);
9673 }
9674 bin_filename = nullptr;
9675 llvm_ir_filename = nullptr;
9676 }
9677
9678 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg,
9679 g->build_mode == BuildModeDebug, is_small, g->enable_time_report, g->tsan_enabled,
9680 g->have_lto, asm_filename, bin_filename, llvm_ir_filename, bitcode_filename))
9681 {
9682 fprintf(stderr, "LLVM failed to emit asm=%s, bin=%s, ir=%s, bc=%s: %s\n",
9683 asm_filename, bin_filename, llvm_ir_filename, bitcode_filename,
9684 err_msg);
9685 exit(1);
9686 }
9687
9688 LLVMDisposeModule(g->module);
9689 g->module = nullptr;
9690 LLVMDisposeTargetData(g->target_data_ref);
9691 g->target_data_ref = nullptr;
9692 LLVMDisposeTargetMachine(g->target_machine);
9693 g->target_machine = nullptr;
9694}
9695
9696struct CIntTypeInfo {
9697 CIntType id;
9698 const char *name;
9699 bool is_signed;
9700};
9701
9702static const CIntTypeInfo c_int_type_infos[] = {
9703 {CIntTypeShort, "c_short", true},
9704 {CIntTypeUShort, "c_ushort", false},
9705 {CIntTypeInt, "c_int", true},
9706 {CIntTypeUInt, "c_uint", false},
9707 {CIntTypeLong, "c_long", true},
9708 {CIntTypeULong, "c_ulong", false},
9709 {CIntTypeLongLong, "c_longlong", true},
9710 {CIntTypeULongLong, "c_ulonglong", false},
9711};
9712
9713static const bool is_signed_list[] = { false, true, };
9714
9715struct GlobalLinkageValue {
9716 GlobalLinkageId id;
9717 const char *name;
9718};
9719
9720static void add_fp_entry(CodeGen *g, const char *name, uint32_t bit_count, LLVMTypeRef type_ref,
9721 ZigType **field)
9722{
9723 ZigType *entry = new_type_table_entry(ZigTypeIdFloat);
9724 entry->llvm_type = type_ref;
9725 entry->size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->llvm_type);
9726 entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type);
9727 entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type);
9728 buf_init_from_str(&entry->name, name);
9729 entry->data.floating.bit_count = bit_count;
9730
9731 entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
9732 entry->size_in_bits, ZigLLVMEncoding_DW_ATE_float());
9733 *field = entry;
9734 g->primitive_type_table.put(&entry->name, entry);
9735}
9736
9737static void define_builtin_types(CodeGen *g) {
9738 {
9739 // if this type is anywhere in the AST, we should never hit codegen.
9740 ZigType *entry = new_type_table_entry(ZigTypeIdInvalid);
9741 buf_init_from_str(&entry->name, "(invalid)");
9742 g->builtin_types.entry_invalid = entry;
9743 }
9744 {
9745 ZigType *entry = new_type_table_entry(ZigTypeIdComptimeFloat);
9746 buf_init_from_str(&entry->name, "comptime_float");
9747 g->builtin_types.entry_num_lit_float = entry;
9748 g->primitive_type_table.put(&entry->name, entry);
9749 }
9750 {
9751 ZigType *entry = new_type_table_entry(ZigTypeIdComptimeInt);
9752 buf_init_from_str(&entry->name, "comptime_int");
9753 g->builtin_types.entry_num_lit_int = entry;
9754 g->primitive_type_table.put(&entry->name, entry);
9755 }
9756 {
9757 ZigType *entry = new_type_table_entry(ZigTypeIdEnumLiteral);
9758 buf_init_from_str(&entry->name, "@Type(.EnumLiteral)");
9759 g->builtin_types.entry_enum_literal = entry;
9760 }
9761 {
9762 ZigType *entry = new_type_table_entry(ZigTypeIdUndefined);
9763 buf_init_from_str(&entry->name, "@Type(.Undefined)");
9764 g->builtin_types.entry_undef = entry;
9765 }
9766 {
9767 ZigType *entry = new_type_table_entry(ZigTypeIdNull);
9768 buf_init_from_str(&entry->name, "@Type(.Null)");
9769 g->builtin_types.entry_null = entry;
9770 }
9771 {
9772 ZigType *entry = new_type_table_entry(ZigTypeIdOpaque);
9773 buf_init_from_str(&entry->name, "(anytype)");
9774 g->builtin_types.entry_anytype = entry;
9775 }
9776
9777 for (size_t i = 0; i < array_length(c_int_type_infos); i += 1) {
9778 const CIntTypeInfo *info = &c_int_type_infos[i];
9779 uint32_t size_in_bits = target_c_type_size_in_bits(g->zig_target, info->id);
9780 bool is_signed = info->is_signed;
9781
9782 ZigType *entry = new_type_table_entry(ZigTypeIdInt);
9783 entry->llvm_type = LLVMIntType(size_in_bits);
9784 entry->size_in_bits = size_in_bits;
9785 entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type);
9786 entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type);
9787
9788 buf_init_from_str(&entry->name, info->name);
9789
9790 entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
9791 size_in_bits,
9792 is_signed ? ZigLLVMEncoding_DW_ATE_signed() : ZigLLVMEncoding_DW_ATE_unsigned());
9793 entry->data.integral.is_signed = is_signed;
9794 entry->data.integral.bit_count = size_in_bits;
9795 g->primitive_type_table.put(&entry->name, entry);
9796
9797 get_c_int_type_ptr(g, info->id)[0] = entry;
9798 }
9799
9800 {
9801 ZigType *entry = new_type_table_entry(ZigTypeIdBool);
9802 entry->llvm_type = LLVMInt1Type();
9803 entry->size_in_bits = 1;
9804 entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type);
9805 entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type);
9806 buf_init_from_str(&entry->name, "bool");
9807 entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
9808 1, ZigLLVMEncoding_DW_ATE_boolean());
9809 g->builtin_types.entry_bool = entry;
9810 g->primitive_type_table.put(&entry->name, entry);
9811 }
9812
9813 for (size_t sign_i = 0; sign_i < array_length(is_signed_list); sign_i += 1) {
9814 bool is_signed = is_signed_list[sign_i];
9815
9816 ZigType *entry = new_type_table_entry(ZigTypeIdInt);
9817 entry->llvm_type = LLVMIntType(g->pointer_size_bytes * 8);
9818 entry->size_in_bits = g->pointer_size_bytes * 8;
9819 entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type);
9820 entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type);
9821
9822 const char u_or_i = is_signed ? 'i' : 'u';
9823 buf_resize(&entry->name, 0);
9824 buf_appendf(&entry->name, "%csize", u_or_i);
9825
9826 entry->data.integral.is_signed = is_signed;
9827 entry->data.integral.bit_count = g->pointer_size_bytes * 8;
9828
9829 entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
9830 8*LLVMStoreSizeOfType(g->target_data_ref, entry->llvm_type),
9831 is_signed ? ZigLLVMEncoding_DW_ATE_signed() : ZigLLVMEncoding_DW_ATE_unsigned());
9832 g->primitive_type_table.put(&entry->name, entry);
9833
9834 if (is_signed) {
9835 g->builtin_types.entry_isize = entry;
9836 } else {
9837 g->builtin_types.entry_usize = entry;
9838 }
9839 }
9840
9841 if (target_is_arm(g->zig_target)) {
9842 add_fp_entry(g, "f16", 16, LLVMHalfType(), &g->builtin_types.entry_f16);
9843 } else {
9844 ZigType *u16_ty = get_int_type(g, false, 16);
9845 add_fp_entry(g, "f16", 16, get_llvm_type(g, u16_ty), &g->builtin_types.entry_f16);
9846 }
9847 add_fp_entry(g, "f32", 32, LLVMFloatType(), &g->builtin_types.entry_f32);
9848 add_fp_entry(g, "f64", 64, LLVMDoubleType(), &g->builtin_types.entry_f64);
9849 add_fp_entry(g, "f128", 128, LLVMFP128Type(), &g->builtin_types.entry_f128);
9850
9851 {
9852 ZigType *entry = new_type_table_entry(ZigTypeIdFloat);
9853 entry->size_in_bits = 80;
9854
9855 buf_init_from_str(&entry->name, "f80");
9856 entry->data.floating.bit_count = 80;
9857
9858 if (target_has_f80(g->zig_target)) {
9859 entry->llvm_type = LLVMX86FP80Type();
9860
9861 // Note the following u64 alignments:
9862 // x86-linux: 4
9863 // x86-windows: 8
9864 // LLVM makes x86_fp80 have the following alignment and sizes regardless
9865 // of operating system:
9866 // x86_64: size=16, align=16
9867 // x86: size=12, align=4
9868 // However in Zig we override x86-windows to have size=16, align=16
9869 // in order for the property to hold that u80 and f80 have the same ABI size.
9870 unsigned u64_alignment = LLVMABIAlignmentOfType(g->target_data_ref, LLVMInt64Type());
9871
9872 if (u64_alignment >= 8) {
9873 entry->abi_size = 16;
9874 entry->abi_align = 16;
9875 } else if (u64_alignment >= 4) {
9876 entry->abi_size = 12;
9877 entry->abi_align = 4;
9878 } else {
9879 entry->abi_size = 10;
9880 entry->abi_align = u64_alignment;
9881 }
9882 } else {
9883 // We use an int here instead of x86_fp80 because on targets such as arm,
9884 // LLVM will give "ERROR: Cannot select" for any instructions involving
9885 // the x86_fp80 type.
9886 ZigType *u80_ty = get_int_type(g, false, 80);
9887 assert(!target_has_f80(g->zig_target));
9888 assert(u80_ty->size_in_bits == entry->size_in_bits);
9889 entry->llvm_type = get_llvm_type(g, u80_ty);
9890 entry->abi_size = u80_ty->abi_size;
9891 entry->abi_align = u80_ty->abi_align;
9892 }
9893
9894 entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
9895 entry->size_in_bits, ZigLLVMEncoding_DW_ATE_unsigned());
9896
9897 g->builtin_types.entry_f80 = entry;
9898 g->primitive_type_table.put(&entry->name, entry);
9899 }
9900
9901 switch (g->zig_target->arch) {
9902 case ZigLLVM_x86:
9903 case ZigLLVM_x86_64:
9904 if (g->zig_target->abi != ZigLLVM_MSVC) {
9905 add_fp_entry(g, "c_longdouble", 80, LLVMX86FP80Type(), &g->builtin_types.entry_c_longdouble);
9906 g->builtin_types.entry_c_longdouble->abi_size = g->builtin_types.entry_f80->abi_size;
9907 g->builtin_types.entry_c_longdouble->abi_align = g->builtin_types.entry_f80->abi_align;
9908 } else {
9909 add_fp_entry(g, "c_longdouble", 64, LLVMDoubleType(), &g->builtin_types.entry_c_longdouble);
9910 }
9911 break;
9912 case ZigLLVM_arm:
9913 case ZigLLVM_armeb:
9914 case ZigLLVM_thumb:
9915 case ZigLLVM_thumbeb:
9916 add_fp_entry(g, "c_longdouble", 64, LLVMDoubleType(), &g->builtin_types.entry_c_longdouble);
9917 break;
9918 case ZigLLVM_aarch64:
9919 case ZigLLVM_aarch64_be:
9920 if (g->zig_target->os == OsWindows || target_os_is_darwin(g->zig_target->os))
9921 add_fp_entry(g, "c_longdouble", 64, LLVMDoubleType(), &g->builtin_types.entry_c_longdouble);
9922 else
9923 add_fp_entry(g, "c_longdouble", 128, LLVMFP128Type(), &g->builtin_types.entry_c_longdouble);
9924 break;
9925 case ZigLLVM_riscv32:
9926 case ZigLLVM_riscv64:
9927 add_fp_entry(g, "c_longdouble", 128, LLVMFP128Type(), &g->builtin_types.entry_c_longdouble);
9928 break;
9929 case ZigLLVM_wasm32:
9930 case ZigLLVM_wasm64:
9931 add_fp_entry(g, "c_longdouble", 128, LLVMFP128Type(), &g->builtin_types.entry_c_longdouble);
9932 break;
9933 case ZigLLVM_mips:
9934 case ZigLLVM_mipsel:
9935 // Assume o32 ABI
9936 add_fp_entry(g, "c_longdouble", 64, LLVMDoubleType(), &g->builtin_types.entry_c_longdouble);
9937 break;
9938 case ZigLLVM_mips64:
9939 case ZigLLVM_mips64el:
9940 add_fp_entry(g, "c_longdouble", 128, LLVMFP128Type(), &g->builtin_types.entry_c_longdouble);
9941 break;
9942 case ZigLLVM_ppc:
9943 case ZigLLVM_ppcle:
9944 case ZigLLVM_ppc64:
9945 case ZigLLVM_ppc64le:
9946 add_fp_entry(g, "c_longdouble", 128, LLVMFP128Type(), &g->builtin_types.entry_c_longdouble);
9947 break;
9948 case ZigLLVM_sparcv9:
9949 add_fp_entry(g, "c_longdouble", 128, LLVMFP128Type(), &g->builtin_types.entry_c_longdouble);
9950 break;
9951 case ZigLLVM_systemz:
9952 add_fp_entry(g, "c_longdouble", 128, LLVMDoubleType(), &g->builtin_types.entry_c_longdouble);
9953 break;
9954 case ZigLLVM_avr:
9955 // It's either a float or a double, depending on a toolchain switch
9956 add_fp_entry(g, "c_longdouble", 64, LLVMDoubleType(), &g->builtin_types.entry_c_longdouble);
9957 break;
9958 case ZigLLVM_msp430:
9959 add_fp_entry(g, "c_longdouble", 64, LLVMDoubleType(), &g->builtin_types.entry_c_longdouble);
9960 break;
9961 case ZigLLVM_bpfel:
9962 case ZigLLVM_bpfeb:
9963 add_fp_entry(g, "c_longdouble", 64, LLVMDoubleType(), &g->builtin_types.entry_c_longdouble);
9964 break;
9965 case ZigLLVM_nvptx:
9966 case ZigLLVM_nvptx64:
9967 add_fp_entry(g, "c_longdouble", 64, LLVMDoubleType(), &g->builtin_types.entry_c_longdouble);
9968 break;
9969 default:
9970 zig_panic("TODO implement mapping for c_longdouble");
9971 }
9972
9973 {
9974 ZigType *entry = new_type_table_entry(ZigTypeIdVoid);
9975 entry->llvm_type = LLVMVoidType();
9976 buf_init_from_str(&entry->name, "void");
9977 entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
9978 0,
9979 ZigLLVMEncoding_DW_ATE_signed());
9980 g->builtin_types.entry_void = entry;
9981 g->primitive_type_table.put(&entry->name, entry);
9982 }
9983 {
9984 ZigType *entry = new_type_table_entry(ZigTypeIdUnreachable);
9985 entry->llvm_type = LLVMVoidType();
9986 buf_init_from_str(&entry->name, "noreturn");
9987 entry->llvm_di_type = g->builtin_types.entry_void->llvm_di_type;
9988 g->builtin_types.entry_unreachable = entry;
9989 g->primitive_type_table.put(&entry->name, entry);
9990 }
9991 {
9992 ZigType *entry = new_type_table_entry(ZigTypeIdMetaType);
9993 buf_init_from_str(&entry->name, "type");
9994 g->builtin_types.entry_type = entry;
9995 g->primitive_type_table.put(&entry->name, entry);
9996 }
9997
9998 g->builtin_types.entry_u8 = get_int_type(g, false, 8);
9999 g->builtin_types.entry_u16 = get_int_type(g, false, 16);
10000 g->builtin_types.entry_u29 = get_int_type(g, false, 29);
10001 g->builtin_types.entry_u32 = get_int_type(g, false, 32);
10002 g->builtin_types.entry_u64 = get_int_type(g, false, 64);
10003 g->builtin_types.entry_i8 = get_int_type(g, true, 8);
10004 g->builtin_types.entry_i32 = get_int_type(g, true, 32);
10005 g->builtin_types.entry_i64 = get_int_type(g, true, 64);
10006
10007 {
10008 g->builtin_types.entry_anyopaque = get_opaque_type(g, nullptr, nullptr, "anyopaque",
10009 buf_create_from_str("anyopaque"));
10010 g->primitive_type_table.put(&g->builtin_types.entry_anyopaque->name, g->builtin_types.entry_anyopaque);
10011 }
10012
10013 {
10014 ZigType *ptr_const_anyopaque = get_pointer_to_type(g,
10015 g->builtin_types.entry_anyopaque, true);
10016 g->builtin_types.entry_opt_ptr_const_anyopaque = get_optional_type(g, ptr_const_anyopaque);
10017 }
10018
10019 {
10020 ZigType *entry = new_type_table_entry(ZigTypeIdErrorSet);
10021 buf_init_from_str(&entry->name, "anyerror");
10022 entry->data.error_set.err_count = UINT32_MAX;
10023
10024 // TODO https://github.com/ziglang/zig/issues/786
10025 g->err_tag_type = g->builtin_types.entry_u16;
10026
10027 entry->size_in_bits = g->err_tag_type->size_in_bits;
10028 entry->abi_align = g->err_tag_type->abi_align;
10029 entry->abi_size = g->err_tag_type->abi_size;
10030
10031 g->builtin_types.entry_global_error_set = entry;
10032
10033 g->errors_by_index.append(nullptr);
10034
10035 g->primitive_type_table.put(&entry->name, entry);
10036 }
10037}
10038
10039static void define_intern_values(CodeGen *g) {
10040 {
10041 auto& value = g->intern.x_undefined;
10042 value.type = g->builtin_types.entry_undef;
10043 value.special = ConstValSpecialStatic;
10044 }
10045 {
10046 auto& value = g->intern.x_void;
10047 value.type = g->builtin_types.entry_void;
10048 value.special = ConstValSpecialStatic;
10049 }
10050 {
10051 auto& value = g->intern.x_null;
10052 value.type = g->builtin_types.entry_null;
10053 value.special = ConstValSpecialStatic;
10054 }
10055 {
10056 auto& value = g->intern.x_unreachable;
10057 value.type = g->builtin_types.entry_unreachable;
10058 value.special = ConstValSpecialStatic;
10059 }
10060 {
10061 auto& value = g->intern.zero_byte;
10062 value.type = g->builtin_types.entry_u8;
10063 value.special = ConstValSpecialStatic;
10064 bigint_init_unsigned(&value.data.x_bigint, 0);
10065 }
10066}
10067
10068static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char *name, size_t count) {
10069 BuiltinFnEntry *builtin_fn = heap::c_allocator.create<BuiltinFnEntry>();
10070 buf_init_from_str(&builtin_fn->name, name);
10071 builtin_fn->id = id;
10072 builtin_fn->param_count = count;
10073 g->builtin_fn_table.put(&builtin_fn->name, builtin_fn);
10074 return builtin_fn;
10075}
10076
10077static void define_builtin_fns(CodeGen *g) {
10078 create_builtin_fn(g, BuiltinFnIdBreakpoint, "breakpoint", 0);
10079 create_builtin_fn(g, BuiltinFnIdReturnAddress, "returnAddress", 0);
10080 create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy", 3);
10081 create_builtin_fn(g, BuiltinFnIdMemset, "memset", 3);
10082 create_builtin_fn(g, BuiltinFnIdSizeof, "sizeOf", 1);
10083 create_builtin_fn(g, BuiltinFnIdAlignOf, "alignOf", 1);
10084 create_builtin_fn(g, BuiltinFnIdField, "field", 2);
10085 create_builtin_fn(g, BuiltinFnIdTypeInfo, "typeInfo", 1);
10086 create_builtin_fn(g, BuiltinFnIdType, "Type", 1);
10087 create_builtin_fn(g, BuiltinFnIdHasField, "hasField", 2);
10088 create_builtin_fn(g, BuiltinFnIdTypeof, "TypeOf", SIZE_MAX);
10089 create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4);
10090 create_builtin_fn(g, BuiltinFnIdSubWithOverflow, "subWithOverflow", 4);
10091 create_builtin_fn(g, BuiltinFnIdMulWithOverflow, "mulWithOverflow", 4);
10092 create_builtin_fn(g, BuiltinFnIdShlWithOverflow, "shlWithOverflow", 4);
10093 create_builtin_fn(g, BuiltinFnIdCInclude, "cInclude", 1);
10094 create_builtin_fn(g, BuiltinFnIdCDefine, "cDefine", 2);
10095 create_builtin_fn(g, BuiltinFnIdCUndef, "cUndef", 1);
10096 create_builtin_fn(g, BuiltinFnIdCtz, "ctz", 1);
10097 create_builtin_fn(g, BuiltinFnIdClz, "clz", 1);
10098 create_builtin_fn(g, BuiltinFnIdPopCount, "popCount", 1);
10099 create_builtin_fn(g, BuiltinFnIdBswap, "byteSwap", 1);
10100 create_builtin_fn(g, BuiltinFnIdBitReverse, "bitReverse", 1);
10101 create_builtin_fn(g, BuiltinFnIdImport, "import", 1);
10102 create_builtin_fn(g, BuiltinFnIdCImport, "cImport", 1);
10103 create_builtin_fn(g, BuiltinFnIdErrName, "errorName", 1);
10104 create_builtin_fn(g, BuiltinFnIdTypeName, "typeName", 1);
10105 create_builtin_fn(g, BuiltinFnIdEmbedFile, "embedFile", 1);
10106 create_builtin_fn(g, BuiltinFnIdCmpxchgWeak, "cmpxchgWeak", 6);
10107 create_builtin_fn(g, BuiltinFnIdCmpxchgStrong, "cmpxchgStrong", 6);
10108 create_builtin_fn(g, BuiltinFnIdFence, "fence", 1);
10109 create_builtin_fn(g, BuiltinFnIdTruncate, "truncate", 2);
10110 create_builtin_fn(g, BuiltinFnIdIntCast, "intCast", 2);
10111 create_builtin_fn(g, BuiltinFnIdFloatCast, "floatCast", 2);
10112 create_builtin_fn(g, BuiltinFnIdIntToFloat, "intToFloat", 2);
10113 create_builtin_fn(g, BuiltinFnIdFloatToInt, "floatToInt", 2);
10114 create_builtin_fn(g, BuiltinFnIdBoolToInt, "boolToInt", 1);
10115 create_builtin_fn(g, BuiltinFnIdErrToInt, "errorToInt", 1);
10116 create_builtin_fn(g, BuiltinFnIdIntToErr, "intToError", 1);
10117 create_builtin_fn(g, BuiltinFnIdEnumToInt, "enumToInt", 1);
10118 create_builtin_fn(g, BuiltinFnIdIntToEnum, "intToEnum", 2);
10119 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
10120 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
10121 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
10122 create_builtin_fn(g, BuiltinFnIdShuffle, "shuffle", 4);
10123 create_builtin_fn(g, BuiltinFnIdSelect, "select", 4);
10124 create_builtin_fn(g, BuiltinFnIdSplat, "splat", 2);
10125 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
10126 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
10127 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
10128 create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1);
10129 create_builtin_fn(g, BuiltinFnIdPtrCast, "ptrCast", 2);
10130 create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2);
10131 create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2);
10132 create_builtin_fn(g, BuiltinFnIdPtrToInt, "ptrToInt", 1);
10133 create_builtin_fn(g, BuiltinFnIdTagName, "tagName", 1);
10134 create_builtin_fn(g, BuiltinFnIdFieldParentPtr, "fieldParentPtr", 3);
10135 create_builtin_fn(g, BuiltinFnIdOffsetOf, "offsetOf", 2);
10136 create_builtin_fn(g, BuiltinFnIdBitOffsetOf, "bitOffsetOf", 2);
10137 create_builtin_fn(g, BuiltinFnIdDivExact, "divExact", 2);
10138 create_builtin_fn(g, BuiltinFnIdDivTrunc, "divTrunc", 2);
10139 create_builtin_fn(g, BuiltinFnIdDivFloor, "divFloor", 2);
10140 create_builtin_fn(g, BuiltinFnIdRem, "rem", 2);
10141 create_builtin_fn(g, BuiltinFnIdMod, "mod", 2);
10142 create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 1);
10143 create_builtin_fn(g, BuiltinFnIdSin, "sin", 1);
10144 create_builtin_fn(g, BuiltinFnIdCos, "cos", 1);
10145 create_builtin_fn(g, BuiltinFnIdTan, "tan", 1);
10146 create_builtin_fn(g, BuiltinFnIdExp, "exp", 1);
10147 create_builtin_fn(g, BuiltinFnIdExp2, "exp2", 1);
10148 create_builtin_fn(g, BuiltinFnIdLog, "log", 1);
10149 create_builtin_fn(g, BuiltinFnIdLog2, "log2", 1);
10150 create_builtin_fn(g, BuiltinFnIdLog10, "log10", 1);
10151 create_builtin_fn(g, BuiltinFnIdFabs, "fabs", 1);
10152 create_builtin_fn(g, BuiltinFnIdFloor, "floor", 1);
10153 create_builtin_fn(g, BuiltinFnIdCeil, "ceil", 1);
10154 create_builtin_fn(g, BuiltinFnIdTrunc, "trunc", 1);
10155 create_builtin_fn(g, BuiltinFnIdNearbyInt, "nearbyInt", 1);
10156 create_builtin_fn(g, BuiltinFnIdRound, "round", 1);
10157 create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);
10158 create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX);
10159 create_builtin_fn(g, BuiltinFnIdShlExact, "shlExact", 2);
10160 create_builtin_fn(g, BuiltinFnIdShrExact, "shrExact", 2);
10161 create_builtin_fn(g, BuiltinFnIdSetEvalBranchQuota, "setEvalBranchQuota", 1);
10162 create_builtin_fn(g, BuiltinFnIdAlignCast, "alignCast", 2);
10163 create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1);
10164 create_builtin_fn(g, BuiltinFnIdExport, "export", 2);
10165 create_builtin_fn(g, BuiltinFnIdExtern, "extern", 2);
10166 create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0);
10167 create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5);
10168 create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3);
10169 create_builtin_fn(g, BuiltinFnIdAtomicStore, "atomicStore", 4);
10170 create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2);
10171 create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
10172 create_builtin_fn(g, BuiltinFnIdHasDecl, "hasDecl", 2);
10173 create_builtin_fn(g, BuiltinFnIdUnionInit, "unionInit", 3);
10174 create_builtin_fn(g, BuiltinFnIdFrameHandle, "frame", 0);
10175 create_builtin_fn(g, BuiltinFnIdFrameType, "Frame", 1);
10176 create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0);
10177 create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1);
10178 create_builtin_fn(g, BuiltinFnIdAs, "as", 2);
10179 create_builtin_fn(g, BuiltinFnIdCall, "call", 3);
10180 create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1);
10181 create_builtin_fn(g, BuiltinFnIdWasmMemorySize, "wasmMemorySize", 1);
10182 create_builtin_fn(g, BuiltinFnIdWasmMemoryGrow, "wasmMemoryGrow", 2);
10183 create_builtin_fn(g, BuiltinFnIdSrc, "src", 0);
10184 create_builtin_fn(g, BuiltinFnIdReduce, "reduce", 2);
10185 create_builtin_fn(g, BuiltinFnIdMaximum, "max", 2);
10186 create_builtin_fn(g, BuiltinFnIdMinimum, "min", 2);
10187 create_builtin_fn(g, BuiltinFnIdPrefetch, "prefetch", 2);
10188 create_builtin_fn(g, BuiltinFnIdAddrSpaceCast, "addrSpaceCast", 2);
10189}
10190
10191static const char *bool_to_str(bool b) {
10192 return b ? "true" : "false";
10193}
10194
10195static const char *build_mode_to_str(BuildMode build_mode) {
10196 switch (build_mode) {
10197 case BuildModeDebug: return "Debug";
10198 case BuildModeSafeRelease: return "ReleaseSafe";
10199 case BuildModeFastRelease: return "ReleaseFast";
10200 case BuildModeSmallRelease: return "ReleaseSmall";
10201 }
10202 zig_unreachable();
10203}
10204
10205static const char *subsystem_to_str(TargetSubsystem subsystem) {
10206 switch (subsystem) {
10207 case TargetSubsystemConsole: return "Console";
10208 case TargetSubsystemWindows: return "Windows";
10209 case TargetSubsystemPosix: return "Posix";
10210 case TargetSubsystemNative: return "Native";
10211 case TargetSubsystemEfiApplication: return "EfiApplication";
10212 case TargetSubsystemEfiBootServiceDriver: return "EfiBootServiceDriver";
10213 case TargetSubsystemEfiRom: return "EfiRom";
10214 case TargetSubsystemEfiRuntimeDriver: return "EfiRuntimeDriver";
10215 case TargetSubsystemAuto: zig_unreachable();
10216 }
10217 zig_unreachable();
10218}
10219
10220// Returns TargetSubsystemAuto to mean "no subsystem"
10221TargetSubsystem detect_subsystem(CodeGen *g) {
10222 if (g->subsystem != TargetSubsystemAuto)
10223 return g->subsystem;
10224 if (g->zig_target->os == OsWindows) {
10225 if (g->stage1.have_dllmain_crt_startup)
10226 return TargetSubsystemAuto;
10227 if (g->stage1.have_c_main || g->is_test_build || g->stage1.have_winmain_crt_startup || g->stage1.have_wwinmain_crt_startup)
10228 return TargetSubsystemConsole;
10229 if (g->stage1.have_winmain || g->stage1.have_wwinmain)
10230 return TargetSubsystemWindows;
10231 } else if (g->zig_target->os == OsUefi) {
10232 return TargetSubsystemEfiApplication;
10233 }
10234 return TargetSubsystemAuto;
10235}
10236
10237static bool detect_err_ret_tracing(CodeGen *g) {
10238 return !g->strip_debug_symbols &&
10239 g->build_mode != BuildModeFastRelease &&
10240 g->build_mode != BuildModeSmallRelease;
10241}
10242
10243static LLVMCodeModel to_llvm_code_model(CodeGen *g) {
10244 switch (g->code_model) {
10245 case CodeModelDefault:
10246 return LLVMCodeModelDefault;
10247 case CodeModelTiny:
10248 return LLVMCodeModelTiny;
10249 case CodeModelSmall:
10250 return LLVMCodeModelSmall;
10251 case CodeModelKernel:
10252 return LLVMCodeModelKernel;
10253 case CodeModelMedium:
10254 return LLVMCodeModelMedium;
10255 case CodeModelLarge:
10256 return LLVMCodeModelLarge;
10257 }
10258
10259 zig_unreachable();
10260}
10261
10262Buf *codegen_generate_builtin_source(CodeGen *g) {
10263 // Note that this only runs when zig0 is building the self-hosted zig compiler code,
10264 // so it makes a few assumption that are always true for that case. Once we have
10265 // built the stage2 zig components then zig is in charge of generating the builtin.zig
10266 // file.
10267
10268 g->have_err_ret_tracing = detect_err_ret_tracing(g);
10269
10270 Buf *contents = buf_alloc();
10271 buf_appendf(contents,
10272 "const std = @import(\"std\");\n"
10273 );
10274
10275 const char *cur_os = nullptr;
10276 {
10277 uint32_t field_count = (uint32_t)target_os_count();
10278 for (uint32_t i = 0; i < field_count; i += 1) {
10279 Os os_type = target_os_enum(i);
10280 const char *name = target_os_name(os_type);
10281
10282 if (os_type == g->zig_target->os) {
10283 cur_os = name;
10284 }
10285 }
10286 }
10287 assert(cur_os != nullptr);
10288
10289 const char *cur_arch = nullptr;
10290 {
10291 uint32_t field_count = (uint32_t)target_arch_count();
10292 for (uint32_t arch_i = 0; arch_i < field_count; arch_i += 1) {
10293 ZigLLVM_ArchType arch = target_arch_enum(arch_i);
10294 const char *arch_name = target_arch_name(arch);
10295 if (arch == g->zig_target->arch) {
10296 cur_arch = arch_name;
10297 }
10298 }
10299
10300 // Workaround to LLVM/Zig naming mismatch.
10301 // LLVM calls it sparcv9, while Zig calls it sparc64.
10302 if (!strcmp(cur_arch, "sparcv9")) {
10303 cur_arch = "sparc64";
10304 }
10305 }
10306 assert(cur_arch != nullptr);
10307
10308 const char *cur_abi = nullptr;
10309 {
10310 uint32_t field_count = (uint32_t)target_abi_count();
10311 for (uint32_t i = 0; i < field_count; i += 1) {
10312 ZigLLVM_EnvironmentType abi = target_abi_enum(i);
10313 const char *name = target_abi_name(abi);
10314
10315 if (abi == g->zig_target->abi) {
10316 cur_abi = name;
10317 }
10318 }
10319 }
10320 assert(cur_abi != nullptr);
10321
10322 const char *cur_obj_fmt = nullptr;
10323 {
10324 uint32_t field_count = (uint32_t)target_oformat_count();
10325 for (uint32_t i = 0; i < field_count; i += 1) {
10326 ZigLLVM_ObjectFormatType oformat = target_oformat_enum(i);
10327 const char *name = target_oformat_name(oformat);
10328
10329 ZigLLVM_ObjectFormatType target_oformat = target_object_format(g->zig_target);
10330 if (oformat == target_oformat) {
10331 cur_obj_fmt = name;
10332 }
10333 }
10334
10335 }
10336 assert(cur_obj_fmt != nullptr);
10337
10338 // If any of these asserts trip then you need to either fix the internal compiler enum
10339 // or the corresponding one in std.Target or std.builtin.
10340 static_assert(ContainerLayoutAuto == 0, "");
10341 static_assert(ContainerLayoutExtern == 1, "");
10342 static_assert(ContainerLayoutPacked == 2, "");
10343
10344 static_assert(CallingConventionUnspecified == 0, "");
10345 static_assert(CallingConventionC == 1, "");
10346 static_assert(CallingConventionNaked == 2, "");
10347 static_assert(CallingConventionAsync == 3, "");
10348 static_assert(CallingConventionInline == 4, "");
10349 static_assert(CallingConventionInterrupt == 5, "");
10350 static_assert(CallingConventionSignal == 6, "");
10351 static_assert(CallingConventionStdcall == 7, "");
10352 static_assert(CallingConventionFastcall == 8, "");
10353 static_assert(CallingConventionVectorcall == 9, "");
10354 static_assert(CallingConventionThiscall == 10, "");
10355 static_assert(CallingConventionAPCS == 11, "");
10356 static_assert(CallingConventionAAPCS == 12, "");
10357 static_assert(CallingConventionAAPCSVFP == 13, "");
10358 static_assert(CallingConventionSysV == 14, "");
10359 static_assert(CallingConventionWin64 == 15, "");
10360
10361 static_assert(BuiltinPtrSizeOne == 0, "");
10362 static_assert(BuiltinPtrSizeMany == 1, "");
10363 static_assert(BuiltinPtrSizeSlice == 2, "");
10364 static_assert(BuiltinPtrSizeC == 3, "");
10365
10366 static_assert(TargetSubsystemConsole == 0, "");
10367 static_assert(TargetSubsystemWindows == 1, "");
10368 static_assert(TargetSubsystemPosix == 2, "");
10369 static_assert(TargetSubsystemNative == 3, "");
10370 static_assert(TargetSubsystemEfiApplication == 4, "");
10371 static_assert(TargetSubsystemEfiBootServiceDriver == 5, "");
10372 static_assert(TargetSubsystemEfiRom == 6, "");
10373 static_assert(TargetSubsystemEfiRuntimeDriver == 7, "");
10374
10375 buf_appendf(contents, "pub const output_mode = std.builtin.OutputMode.Obj;\n");
10376 buf_appendf(contents, "pub const link_mode = std.builtin.LinkMode.%s;\n", ZIG_QUOTE(ZIG_LINK_MODE));
10377 buf_appendf(contents, "pub const is_test = false;\n");
10378 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
10379 buf_appendf(contents, "pub const abi = std.Target.Abi.%s;\n", cur_abi);
10380 buf_appendf(contents, "pub const cpu = std.Target.Cpu.baseline(.%s);\n", cur_arch);
10381 buf_appendf(contents, "pub const os = std.Target.Os.Tag.defaultVersionRange(.%s, .%s);\n", cur_os, cur_arch);
10382 buf_appendf(contents,
10383 "pub const target = std.Target{\n"
10384 " .cpu = cpu,\n"
10385 " .os = os,\n"
10386 " .abi = abi,\n"
10387 " .ofmt = object_format,\n"
10388 "};\n"
10389 );
10390
10391 buf_appendf(contents, "pub const object_format = std.Target.ObjectFormat.%s;\n", cur_obj_fmt);
10392 buf_appendf(contents, "pub const mode = std.builtin.Mode.%s;\n", build_mode_to_str(g->build_mode));
10393 buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->link_libc));
10394 buf_appendf(contents, "pub const link_libcpp = %s;\n", bool_to_str(g->link_libcpp));
10395 buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));
10396 buf_appendf(contents, "pub const valgrind_support = false;\n");
10397 buf_appendf(contents, "pub const sanitize_thread = false;\n");
10398 buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
10399 buf_appendf(contents, "pub const position_independent_executable = %s;\n", bool_to_str(g->have_pie));
10400 buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols));
10401 buf_appendf(contents, "pub const code_model = std.builtin.CodeModel.default;\n");
10402 buf_appendf(contents, "pub const zig_backend = std.builtin.CompilerBackend.stage1;\n");
10403
10404 {
10405 TargetSubsystem detected_subsystem = detect_subsystem(g);
10406 if (detected_subsystem != TargetSubsystemAuto) {
10407 buf_appendf(contents, "pub const explicit_subsystem = std.builtin.SubSystem.%s;\n", subsystem_to_str(detected_subsystem));
10408 }
10409 }
10410
10411 return contents;
10412}
10413
10414static ZigPackage *create_test_runner_pkg(CodeGen *g) {
10415 return codegen_create_package(g, buf_ptr(g->zig_lib_dir), "test_runner.zig", "");
10416}
10417
10418static Error define_builtin_compile_vars(CodeGen *g) {
10419 Error err;
10420
10421 if (g->std_package == nullptr)
10422 return ErrorNone;
10423
10424 assert(g->main_pkg);
10425
10426 const char *builtin_zig_basename = "builtin.zig";
10427
10428 Buf *contents;
10429 if (g->builtin_zig_path == nullptr) {
10430 // Then this is zig0 building stage2. We can make many assumptions about the compilation.
10431 Buf *out_dir = buf_alloc();
10432 os_path_split(&g->o_file_output_path, out_dir, nullptr);
10433 g->builtin_zig_path = buf_alloc();
10434 os_path_join(out_dir, buf_create_from_str(builtin_zig_basename), g->builtin_zig_path);
10435
10436 Buf *resolve_paths[] = { g->builtin_zig_path, };
10437 *g->builtin_zig_path = os_path_resolve(resolve_paths, 1);
10438
10439 contents = codegen_generate_builtin_source(g);
10440 if ((err = os_write_file(g->builtin_zig_path, contents))) {
10441 fprintf(stderr, "Unable to write file '%s': %s\n", buf_ptr(g->builtin_zig_path), err_str(err));
10442 exit(1);
10443 }
10444
10445 g->compile_var_package = new_package(buf_ptr(out_dir), builtin_zig_basename, "builtin");
10446 } else {
10447 Buf *resolve_paths[] = { g->builtin_zig_path, };
10448 *g->builtin_zig_path = os_path_resolve(resolve_paths, 1);
10449
10450 contents = buf_alloc();
10451 if ((err = os_fetch_file_path(g->builtin_zig_path, contents))) {
10452 fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(g->builtin_zig_path), err_str(err));
10453 exit(1);
10454 }
10455 Buf builtin_dirname = BUF_INIT;
10456 os_path_dirname(g->builtin_zig_path, &builtin_dirname);
10457 g->compile_var_package = new_package(buf_ptr(&builtin_dirname), builtin_zig_basename, "builtin");
10458 }
10459
10460 if (g->is_test_build) {
10461 if (g->test_runner_package == nullptr) {
10462 g->test_runner_package = create_test_runner_pkg(g);
10463 }
10464 g->root_pkg = g->test_runner_package;
10465 } else {
10466 g->root_pkg = g->main_pkg;
10467 }
10468
10469 ZigPackage *compiler_rt_pkg = codegen_create_package(g, buf_ptr(g->zig_lib_dir),
10470 "compiler_rt.zig", "compiler_rt");
10471
10472 g->compile_var_package->package_table.put(buf_create_from_str("std"), g->std_package);
10473 g->main_pkg->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
10474 g->main_pkg->package_table.put(buf_create_from_str("root"), g->root_pkg);
10475 g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
10476 g->std_package->package_table.put(buf_create_from_str("std"), g->std_package);
10477 g->std_package->package_table.put(buf_create_from_str("root"), g->root_pkg);
10478 g->std_package->package_table.put(buf_create_from_str("compiler_rt"), compiler_rt_pkg);
10479 g->compile_var_import = add_source_file(g, g->compile_var_package, g->builtin_zig_path, contents,
10480 SourceKindPkgMain);
10481
10482 return ErrorNone;
10483}
10484
10485static void init(CodeGen *g) {
10486 if (g->module)
10487 return;
10488
10489 codegen_add_time_event(g, "Initialize");
10490 {
10491 const char *progress_name = "Initialize";
10492 codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node,
10493 progress_name, strlen(progress_name), 0));
10494 }
10495
10496 g->have_err_ret_tracing = detect_err_ret_tracing(g);
10497
10498 assert(g->root_out_name);
10499 g->module = LLVMModuleCreateWithName(buf_ptr(g->root_out_name));
10500
10501 LLVMSetTarget(g->module, buf_ptr(&g->llvm_triple_str));
10502
10503 if (target_object_format(g->zig_target) == ZigLLVM_COFF) {
10504 ZigLLVMAddModuleCodeViewFlag(g->module);
10505 } else {
10506 ZigLLVMAddModuleDebugInfoFlag(g->module);
10507 }
10508
10509 LLVMTargetRef target_ref;
10510 char *err_msg = nullptr;
10511 if (LLVMGetTargetFromTriple(buf_ptr(&g->llvm_triple_str), &target_ref, &err_msg)) {
10512 fprintf(stderr,
10513 "Zig is expecting LLVM to understand this target: '%s'\n"
10514 "However LLVM responded with: \"%s\"\n"
10515 "Zig is unable to continue. This is a bug in Zig:\n"
10516 "https://github.com/ziglang/zig/issues/438\n"
10517 , buf_ptr(&g->llvm_triple_str), err_msg);
10518 exit(1);
10519 }
10520
10521 bool is_optimized = g->build_mode != BuildModeDebug;
10522 LLVMCodeGenOptLevel opt_level = is_optimized ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone;
10523
10524 LLVMRelocMode reloc_mode;
10525 if (g->have_pic) {
10526 reloc_mode = LLVMRelocPIC;
10527 } else if (g->link_mode_dynamic) {
10528 reloc_mode = LLVMRelocDynamicNoPic;
10529 } else {
10530 reloc_mode = LLVMRelocStatic;
10531 }
10532
10533 if (g->have_pic) {
10534 ZigLLVMSetModulePICLevel(g->module);
10535 }
10536
10537 if (g->have_pie) {
10538 ZigLLVMSetModulePIELevel(g->module);
10539 }
10540
10541 if (g->code_model != CodeModelDefault) {
10542 ZigLLVMSetModuleCodeModel(g->module, to_llvm_code_model(g));
10543 }
10544
10545 const char *target_specific_cpu_args = "";
10546 const char *target_specific_features = "";
10547
10548 if (g->zig_target->is_native_cpu) {
10549 target_specific_cpu_args = ZigLLVMGetHostCPUName();
10550 target_specific_features = ZigLLVMGetNativeFeatures();
10551 }
10552
10553 // Override CPU and features if defined by user.
10554 if (g->zig_target->llvm_cpu_name != nullptr) {
10555 target_specific_cpu_args = g->zig_target->llvm_cpu_name;
10556 }
10557 if (g->zig_target->llvm_cpu_features != nullptr) {
10558 target_specific_features = g->zig_target->llvm_cpu_features;
10559 }
10560 if (g->verbose_llvm_cpu_features) {
10561 fprintf(stderr, "name=%s triple=%s\n", buf_ptr(g->root_out_name), buf_ptr(&g->llvm_triple_str));
10562 fprintf(stderr, "name=%s target_specific_cpu_args=%s\n", buf_ptr(g->root_out_name), target_specific_cpu_args);
10563 fprintf(stderr, "name=%s target_specific_features=%s\n", buf_ptr(g->root_out_name), target_specific_features);
10564 }
10565
10566 // TODO handle float ABI better- it should depend on the ABI portion of std.Target
10567 ZigLLVMABIType float_abi = ZigLLVMABITypeDefault;
10568
10569 const char *abi_name = g->zig_target->llvm_target_abi;
10570 if (abi_name == nullptr && target_is_riscv(g->zig_target)) {
10571 // RISC-V Linux defaults to ilp32d/lp64d
10572 if (g->zig_target->os == OsLinux) {
10573 abi_name = (g->zig_target->arch == ZigLLVM_riscv32) ? "ilp32d" : "lp64d";
10574 } else {
10575 abi_name = (g->zig_target->arch == ZigLLVM_riscv32) ? "ilp32" : "lp64";
10576 }
10577 }
10578
10579 g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str),
10580 target_specific_cpu_args, target_specific_features, opt_level, reloc_mode,
10581 to_llvm_code_model(g), g->function_sections, float_abi, abi_name);
10582
10583 g->target_data_ref = LLVMCreateTargetDataLayout(g->target_machine);
10584
10585 char *layout_str = LLVMCopyStringRepOfTargetData(g->target_data_ref);
10586 LLVMSetDataLayout(g->module, layout_str);
10587
10588 assert(g->pointer_size_bytes == LLVMPointerSize(g->target_data_ref));
10589 g->is_big_endian = (LLVMByteOrder(g->target_data_ref) == LLVMBigEndian);
10590
10591 g->builder = LLVMCreateBuilder();
10592 g->dbuilder = ZigLLVMCreateDIBuilder(g->module, true);
10593
10594 // Don't use the version string here, llvm misparses it when it includes the git revision.
10595 Stage2SemVer semver = stage2_version();
10596 Buf *producer = buf_sprintf("zig %d.%d.%d", semver.major, semver.minor, semver.patch);
10597 const char *flags = "";
10598 unsigned runtime_version = 0;
10599
10600 // For macOS stack traces, we want to avoid having to parse the compilation unit debug
10601 // info. As long as each debug info file has a path independent of the compilation unit
10602 // directory (DW_AT_comp_dir), then we never have to look at the compilation unit debug
10603 // info. If we provide an absolute path to LLVM here for the compilation unit debug info,
10604 // LLVM will emit DWARF info that depends on DW_AT_comp_dir. To avoid this, we pass "."
10605 // for the compilation unit directory. This forces each debug file to have a directory
10606 // rather than be relative to DW_AT_comp_dir. According to DWARF 5, debug files will
10607 // no longer reference DW_AT_comp_dir, for the purpose of being able to support the
10608 // common practice of stripping all but the line number sections from an executable.
10609 const char *compile_unit_dir = target_os_is_darwin(g->zig_target->os) ? "." :
10610 buf_ptr(&g->main_pkg->root_src_dir);
10611
10612 ZigLLVMDIFile *compile_unit_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(g->root_out_name),
10613 compile_unit_dir);
10614 g->compile_unit = ZigLLVMCreateCompileUnit(g->dbuilder, ZigLLVMLang_DW_LANG_C99(),
10615 compile_unit_file, buf_ptr(producer), is_optimized, flags, runtime_version,
10616 "", 0, !g->strip_debug_symbols);
10617
10618 // This is for debug stuff that doesn't have a real file.
10619 g->dummy_di_file = nullptr;
10620
10621 define_builtin_types(g);
10622 define_intern_values(g);
10623
10624 Stage1AirInst *sentinel_instructions = heap::c_allocator.allocate<Stage1AirInst>(2);
10625 g->invalid_inst_gen = &sentinel_instructions[0];
10626 g->invalid_inst_gen->value = g->pass1_arena->create<ZigValue>();
10627 g->invalid_inst_gen->value->type = g->builtin_types.entry_invalid;
10628
10629 g->unreach_instruction = &sentinel_instructions[1];
10630 g->unreach_instruction->value = g->pass1_arena->create<ZigValue>();
10631 g->unreach_instruction->value->type = g->builtin_types.entry_unreachable;
10632
10633 g->invalid_inst_src = heap::c_allocator.create<Stage1ZirInst>();
10634
10635 define_builtin_fns(g);
10636 Error err;
10637 if ((err = define_builtin_compile_vars(g))) {
10638 fprintf(stderr, "Unable to create builtin.zig: %s\n", err_str(err));
10639 exit(1);
10640 }
10641}
10642
10643static void update_test_functions_builtin_decl(CodeGen *g) {
10644 Error err;
10645
10646 assert(g->is_test_build);
10647
10648 if (g->test_fns.length == 0) {
10649 fprintf(stderr, "No tests to run.\n");
10650 exit(0);
10651 }
10652
10653 ZigType *fn_type = get_test_fn_type(g);
10654
10655 ZigValue *test_fn_type_val = get_builtin_value(g, "TestFn");
10656 assert(test_fn_type_val->type->id == ZigTypeIdMetaType);
10657 ZigType *struct_type = test_fn_type_val->data.x_type;
10658 if ((err = type_resolve(g, struct_type, ResolveStatusSizeKnown)))
10659 zig_unreachable();
10660
10661 ZigValue *test_fn_array = g->pass1_arena->create<ZigValue>();
10662 test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length, nullptr);
10663 test_fn_array->special = ConstValSpecialStatic;
10664 test_fn_array->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(g->test_fns.length);
10665
10666 for (size_t i = 0; i < g->test_fns.length; i += 1) {
10667 ZigFn *test_fn_entry = g->test_fns.at(i);
10668
10669 ZigValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];
10670 this_val->special = ConstValSpecialStatic;
10671 this_val->type = struct_type;
10672 this_val->parent.id = ConstParentIdArray;
10673 this_val->parent.data.p_array.array_val = test_fn_array;
10674 this_val->parent.data.p_array.elem_index = i;
10675 this_val->data.x_struct.fields = alloc_const_vals_ptrs(g, 3);
10676
10677 ZigValue *name_field = this_val->data.x_struct.fields[0];
10678 ZigValue *name_array_val = create_const_str_lit(g, &test_fn_entry->symbol_name)->data.x_ptr.data.ref.pointee;
10679 init_const_slice(g, name_field, name_array_val, 0, buf_len(&test_fn_entry->symbol_name), true, nullptr);
10680
10681 ZigValue *fn_field = this_val->data.x_struct.fields[1];
10682 fn_field->type = fn_type;
10683 fn_field->special = ConstValSpecialStatic;
10684 fn_field->data.x_ptr.special = ConstPtrSpecialFunction;
10685 fn_field->data.x_ptr.mut = ConstPtrMutComptimeConst;
10686 fn_field->data.x_ptr.data.fn.fn_entry = test_fn_entry;
10687
10688 ZigValue *frame_size_field = this_val->data.x_struct.fields[2];
10689 frame_size_field->type = get_optional_type(g, g->builtin_types.entry_usize);
10690 frame_size_field->special = ConstValSpecialStatic;
10691 frame_size_field->data.x_optional = nullptr;
10692
10693 if (fn_is_async(test_fn_entry)) {
10694 frame_size_field->data.x_optional = g->pass1_arena->create<ZigValue>();
10695 frame_size_field->data.x_optional->special = ConstValSpecialStatic;
10696 frame_size_field->data.x_optional->type = g->builtin_types.entry_usize;
10697 bigint_init_unsigned(&frame_size_field->data.x_optional->data.x_bigint,
10698 test_fn_entry->frame_type->abi_size);
10699 }
10700 }
10701 report_errors_and_maybe_exit(g);
10702
10703 ZigValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true, nullptr);
10704
10705 update_compile_var(g, buf_create_from_str("test_functions"), test_fn_slice);
10706 assert(g->test_runner_package != nullptr);
10707}
10708
10709static Buf *get_resolved_root_src_path(CodeGen *g) {
10710 // TODO memoize
10711 if (buf_len(&g->main_pkg->root_src_path) == 0)
10712 return nullptr;
10713
10714 Buf rel_full_path = BUF_INIT;
10715 os_path_join(&g->main_pkg->root_src_dir, &g->main_pkg->root_src_path, &rel_full_path);
10716
10717 Buf *resolved_path = buf_alloc();
10718 Buf *resolve_paths[] = {&rel_full_path};
10719 *resolved_path = os_path_resolve(resolve_paths, 1);
10720
10721 return resolved_path;
10722}
10723
10724static void gen_root_source(CodeGen *g) {
10725 Buf *resolved_path = get_resolved_root_src_path(g);
10726 if (resolved_path == nullptr)
10727 return;
10728
10729 Buf *source_code = buf_alloc();
10730 Error err;
10731 // No need for using the caching system for this file fetch because it is handled
10732 // separately.
10733 if ((err = os_fetch_file_path(resolved_path, source_code))) {
10734 fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(resolved_path), err_str(err));
10735 exit(1);
10736 }
10737
10738 ZigType *root_import_alias = add_source_file(g, g->main_pkg, resolved_path, source_code, SourceKindRoot);
10739 assert(root_import_alias == g->root_import);
10740
10741 assert(g->root_out_name);
10742
10743 // Zig has lazy top level definitions. Here we semantically analyze the panic function.
10744 Buf *import_target_path;
10745 Buf full_path = BUF_INIT;
10746 ZigType *std_import;
10747 if ((err = analyze_import(g, g->root_import, buf_create_from_str("std"), &std_import,
10748 &import_target_path, &full_path)))
10749 {
10750 if (err == ErrorFileNotFound) {
10751 fprintf(stderr, "unable to find '%s'", buf_ptr(import_target_path));
10752 } else {
10753 fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(&full_path), err_str(err));
10754 }
10755 exit(1);
10756 }
10757
10758 Tld *builtin_tld = find_decl(g, &get_container_scope(std_import)->base,
10759 buf_create_from_str("builtin"));
10760 assert(builtin_tld != nullptr);
10761 resolve_top_level_decl(g, builtin_tld, nullptr, false);
10762 report_errors_and_maybe_exit(g);
10763 assert(builtin_tld->id == TldIdVar);
10764 TldVar *builtin_tld_var = (TldVar*)builtin_tld;
10765 ZigValue *builtin_val = builtin_tld_var->var->const_value;
10766 assert(builtin_val->type->id == ZigTypeIdMetaType);
10767 g->std_builtin_import = builtin_val->data.x_type;
10768
10769 Tld *panic_tld = find_decl(g, &get_container_scope(g->std_builtin_import)->base,
10770 buf_create_from_str("panic"));
10771 assert(panic_tld != nullptr);
10772 resolve_top_level_decl(g, panic_tld, nullptr, false);
10773 report_errors_and_maybe_exit(g);
10774 assert(panic_tld->id == TldIdVar);
10775 TldVar *panic_tld_var = (TldVar*)panic_tld;
10776 ZigValue *panic_fn_val = panic_tld_var->var->const_value;
10777 assert(panic_fn_val->type->id == ZigTypeIdFn);
10778 assert(panic_fn_val->data.x_ptr.special == ConstPtrSpecialFunction);
10779 g->panic_fn = panic_fn_val->data.x_ptr.data.fn.fn_entry;
10780 assert(g->panic_fn != nullptr);
10781
10782 if (g->include_compiler_rt) {
10783 Buf *import_target_path;
10784 Buf full_path = BUF_INIT;
10785 ZigType *compiler_rt_import;
10786 if ((err = analyze_import(g, std_import, buf_create_from_str("compiler_rt"),
10787 &compiler_rt_import, &import_target_path, &full_path)))
10788 {
10789 if (err == ErrorFileNotFound) {
10790 fprintf(stderr, "unable to find '%s'\n", buf_ptr(import_target_path));
10791 } else {
10792 fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(&full_path), err_str(err));
10793 }
10794 exit(1);
10795 }
10796 }
10797
10798 if (!g->error_during_imports) {
10799 semantic_analyze(g);
10800 }
10801 report_errors_and_maybe_exit(g);
10802
10803 if (g->is_test_build) {
10804 update_test_functions_builtin_decl(g);
10805 if (!g->error_during_imports) {
10806 semantic_analyze(g);
10807 }
10808 }
10809
10810 report_errors_and_maybe_exit(g);
10811
10812}
10813
10814void codegen_print_timing_report(CodeGen *g, FILE *f) {
10815 double start_time = g->timing_events.at(0).time;
10816 double end_time = g->timing_events.last().time;
10817 double total = end_time - start_time;
10818 fprintf(f, "%20s%12s%12s%12s%12s\n", "Name", "Start", "End", "Duration", "Percent");
10819 for (size_t i = 0; i < g->timing_events.length - 1; i += 1) {
10820 TimeEvent *te = &g->timing_events.at(i);
10821 TimeEvent *next_te = &g->timing_events.at(i + 1);
10822 fprintf(f, "%20s%12.4f%12.4f%12.4f%12.4f\n", te->name,
10823 te->time - start_time,
10824 next_te->time - start_time,
10825 next_te->time - te->time,
10826 (next_te->time - te->time) / total);
10827 }
10828 fprintf(f, "%20s%12.4f%12.4f%12.4f%12.4f\n", "Total", 0.0, total, total, 1.0);
10829}
10830
10831void codegen_add_time_event(CodeGen *g, const char *name) {
10832 OsTimeStamp timestamp = os_timestamp_monotonic();
10833 double seconds = (double)timestamp.sec;
10834 seconds += ((double)timestamp.nsec) / 1000000000.0;
10835 g->timing_events.append({seconds, name});
10836}
10837
10838void codegen_build_object(CodeGen *g) {
10839 g->have_err_ret_tracing = detect_err_ret_tracing(g);
10840
10841 init(g);
10842
10843 codegen_add_time_event(g, "Semantic Analysis");
10844 const char *progress_name = "Semantic Analysis";
10845 codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node,
10846 progress_name, strlen(progress_name), 0));
10847
10848 gen_root_source(g);
10849
10850
10851 codegen_add_time_event(g, "Code Generation");
10852 {
10853 const char *progress_name = "Code Generation";
10854 codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node,
10855 progress_name, strlen(progress_name), 0));
10856 }
10857
10858 do_code_gen(g);
10859 codegen_add_time_event(g, "LLVM Emit Object");
10860 {
10861 const char *progress_name = "LLVM Emit Object";
10862 codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node,
10863 progress_name, strlen(progress_name), 0));
10864 }
10865 zig_llvm_emit_output(g);
10866
10867 codegen_add_time_event(g, "Done");
10868 codegen_switch_sub_prog_node(g, nullptr);
10869
10870 // append all export symbols to stage2 so we can provide them to the linker
10871 if (target_is_wasm(g->zig_target)){
10872 Error err;
10873 auto export_it = g->exported_symbol_names.entry_iterator();
10874 decltype(g->exported_symbol_names)::Entry *curr_entry = nullptr;
10875 while ((curr_entry = export_it.next()) != nullptr) {
10876 if ((err = stage2_append_symbol(&g->stage1, buf_ptr(curr_entry->key), buf_len(curr_entry->key)))) {
10877 fprintf(stderr, "Unable to export symbol '%s': %s\n", buf_ptr(curr_entry->key), err_str(err));
10878 }
10879 }
10880 }
10881}
10882
10883ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path,
10884 const char *pkg_path)
10885{
10886 init(g);
10887 ZigPackage *pkg = new_package(root_src_dir, root_src_path, pkg_path);
10888 if (g->std_package != nullptr) {
10889 assert(g->compile_var_package != nullptr);
10890 pkg->package_table.put(buf_create_from_str("std"), g->std_package);
10891
10892 pkg->package_table.put(buf_create_from_str("root"), g->root_pkg);
10893
10894 pkg->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
10895 }
10896 return pkg;
10897}
10898
10899void codegen_destroy(CodeGen *g) {
10900 if (g->pass1_arena != nullptr) {
10901 g->pass1_arena->destruct(&heap::c_allocator);
10902 g->pass1_arena = nullptr;
10903 }
10904 heap::c_allocator.destroy<CodeGen>(g);
10905}
10906
10907CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
10908 BuildMode build_mode, Buf *override_lib_dir,
10909 bool is_test_build)
10910{
10911 CodeGen *g = heap::c_allocator.create<CodeGen>();
10912 g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1");
10913
10914 g->subsystem = TargetSubsystemAuto;
10915 g->zig_target = target;
10916
10917 assert(override_lib_dir != nullptr);
10918 g->zig_lib_dir = override_lib_dir;
10919
10920 g->zig_std_dir = buf_alloc();
10921 os_path_join(g->zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir);
10922
10923 g->build_mode = build_mode;
10924 g->import_table.init(32);
10925 g->builtin_fn_table.init(32);
10926 g->primitive_type_table.init(32);
10927 g->type_table.init(32);
10928 g->fn_type_table.init(32);
10929 g->error_table.init(16);
10930 g->generic_table.init(16);
10931 g->llvm_fn_table.init(16);
10932 g->memoized_fn_eval_table.init(16);
10933 g->exported_symbol_names.init(8);
10934 g->external_symbol_names.init(8);
10935 g->string_literals_table.init(16);
10936 g->type_info_cache.init(32);
10937 g->one_possible_values.init(32);
10938 g->is_test_build = is_test_build;
10939 g->is_single_threaded = false;
10940 g->code_model = CodeModelDefault;
10941 buf_resize(&g->global_asm, 0);
10942
10943 for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) {
10944 g->external_symbol_names.put(buf_create_from_str(symbols_that_llvm_depends_on[i]), nullptr);
10945 }
10946
10947 if (root_src_path) {
10948 Buf *root_pkg_path;
10949 Buf *rel_root_src_path;
10950 if (main_pkg_path == nullptr) {
10951 Buf *src_basename = buf_alloc();
10952 Buf *src_dir = buf_alloc();
10953 os_path_split(root_src_path, src_dir, src_basename);
10954
10955 if (buf_len(src_basename) == 0) {
10956 fprintf(stderr, "Invalid root source path: %s\n", buf_ptr(root_src_path));
10957 exit(1);
10958 }
10959 root_pkg_path = src_dir;
10960 rel_root_src_path = src_basename;
10961 } else {
10962 Buf resolved_root_src_path = os_path_resolve(&root_src_path, 1);
10963 Buf resolved_main_pkg_path = os_path_resolve(&main_pkg_path, 1);
10964
10965 if (!buf_starts_with_buf(&resolved_root_src_path, &resolved_main_pkg_path)) {
10966 fprintf(stderr, "Root source path '%s' outside main package path '%s'\n",
10967 buf_ptr(root_src_path), buf_ptr(main_pkg_path));
10968 exit(1);
10969 }
10970 root_pkg_path = main_pkg_path;
10971 rel_root_src_path = buf_create_from_mem(
10972 buf_ptr(&resolved_root_src_path) + buf_len(&resolved_main_pkg_path) + 1,
10973 buf_len(&resolved_root_src_path) - buf_len(&resolved_main_pkg_path) - 1);
10974 }
10975
10976 g->main_pkg = new_package(buf_ptr(root_pkg_path), buf_ptr(rel_root_src_path), "");
10977 g->std_package = new_package(buf_ptr(g->zig_std_dir), "std.zig", "std");
10978 g->main_pkg->package_table.put(buf_create_from_str("std"), g->std_package);
10979 } else {
10980 g->main_pkg = new_package(".", "", "");
10981 }
10982
10983 target_triple_llvm(&g->llvm_triple_str, g->zig_target);
10984 g->pointer_size_bytes = target_arch_pointer_bit_width(g->zig_target->arch) / 8;
10985
10986 if (!target_has_debug_info(g->zig_target)) {
10987 g->strip_debug_symbols = true;
10988 }
10989
10990 return g;
10991}
10992
10993bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type) {
10994 return g->have_err_ret_tracing &&
10995 (return_type->id == ZigTypeIdErrorUnion ||
10996 return_type->id == ZigTypeIdErrorSet);
10997}
10998
10999bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn, bool is_async) {
11000 if (is_async) {
11001 return g->have_err_ret_tracing && (fn->calls_or_awaits_errorable_fn ||
11002 codegen_fn_has_err_ret_tracing_arg(g, fn->type_entry->data.fn.fn_type_id.return_type));
11003 } else {
11004 return g->have_err_ret_tracing && fn->calls_or_awaits_errorable_fn &&
11005 !codegen_fn_has_err_ret_tracing_arg(g, fn->type_entry->data.fn.fn_type_id.return_type);
11006 }
11007}
11008
11009void codegen_switch_sub_prog_node(CodeGen *g, Stage2ProgressNode *node) {
11010 if (g->sub_progress_node != nullptr) {
11011 stage2_progress_end(g->sub_progress_node);
11012 }
11013 g->sub_progress_node = node;
11014}
11015
11016ZigValue *CodeGen::Intern::for_undefined() {
11017 return &this->x_undefined;
11018}
11019
11020ZigValue *CodeGen::Intern::for_void() {
11021 return &this->x_void;
11022}
11023
11024ZigValue *CodeGen::Intern::for_null() {
11025 return &this->x_null;
11026}
11027
11028ZigValue *CodeGen::Intern::for_unreachable() {
11029 return &this->x_unreachable;
11030}
11031
11032ZigValue *CodeGen::Intern::for_zero_byte() {
11033 return &this->zero_byte;
11034}
src/stage1/codegen.hpp deleted-40
...@@ -1,40 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_CODEGEN_HPP
9#define ZIG_CODEGEN_HPP
10
11#include "parser.hpp"
12#include "errmsg.hpp"
13#include "target.hpp"
14#include "stage2.h"
15
16#include <stdio.h>
17
18CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
19 BuildMode build_mode, Buf *zig_lib_dir, bool is_test_build);
20
21void codegen_build_object(CodeGen *g);
22void codegen_destroy(CodeGen *);
23
24void codegen_add_time_event(CodeGen *g, const char *name);
25void codegen_print_timing_report(CodeGen *g, FILE *f);
26
27ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path,
28 const char *pkg_path);
29
30TargetSubsystem detect_subsystem(CodeGen *g);
31
32bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type);
33bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn, bool is_async);
34
35ATTRIBUTE_NORETURN
36void codegen_report_errors_and_exit(CodeGen *g);
37
38void codegen_switch_sub_prog_node(CodeGen *g, Stage2ProgressNode *node);
39
40#endif
src/stage1/config.h.in deleted-30
...@@ -1,30 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_CONFIG_H
9#define ZIG_CONFIG_H
10
11// Used by zig0.cpp
12#define ZIG_VERSION_MAJOR @ZIG_VERSION_MAJOR@
13#define ZIG_VERSION_MINOR @ZIG_VERSION_MINOR@
14#define ZIG_VERSION_PATCH @ZIG_VERSION_PATCH@
15#define ZIG_VERSION_STRING "@RESOLVED_ZIG_VERSION@"
16
17// Used by build.zig for communicating build information to self hosted build.
18#define ZIG_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@"
19#define ZIG_LLVM_LINK_MODE "@LLVM_LINK_MODE@"
20#define ZIG_CMAKE_PREFIX_PATH "@ZIG_CMAKE_PREFIX_PATH@"
21#define ZIG_CXX_COMPILER "@CMAKE_CXX_COMPILER@"
22#define ZIG_LLD_INCLUDE_PATH "@LLD_INCLUDE_DIRS@"
23#define ZIG_LLD_LIBRARIES "@LLD_LIBRARIES@"
24#define ZIG_CLANG_LIBRARIES "@CLANG_LIBRARIES@"
25#define ZIG_LLVM_INCLUDE_PATH "@LLVM_INCLUDE_DIRS@"
26#define ZIG_LLVM_LIB_PATH "@LLVM_LIBDIRS@"
27#define ZIG_LLVM_LIBRARIES "@LLVM_LIBRARIES@"
28#define ZIG_DIA_GUIDS_LIB "@ZIG_DIA_GUIDS_LIB_ESCAPED@"
29
30#endif
src/stage1/empty.cpp deleted
src/stage1/errmsg.cpp deleted-135
...@@ -1,135 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "errmsg.hpp"
9#include "os.hpp"
10
11#include <stdio.h>
12
13enum ErrType {
14 ErrTypeError,
15 ErrTypeNote,
16};
17
18static void print_err_msg_type(ErrorMsg *err, ErrColor color, ErrType err_type) {
19 bool supports_color = os_stderr_supports_color();
20 bool use_colors = color == ErrColorOn || (color == ErrColorAuto && supports_color);
21
22 // Show the error location, if available
23 if (err->path != nullptr) {
24 const char *path = buf_ptr(err->path);
25 Slice<const char> pathslice{path, strlen(path)};
26
27 // Cache cwd
28 static Buf *cwdbuf{nullptr};
29 static Slice<const char> cwd;
30
31 if (cwdbuf == nullptr) {
32 cwdbuf = buf_alloc();
33 Error err = os_get_cwd(cwdbuf);
34 if (err != ErrorNone)
35 zig_panic("get cwd failed");
36 buf_append_char(cwdbuf, ZIG_OS_SEP_CHAR);
37 cwd.ptr = buf_ptr(cwdbuf);
38 cwd.len = strlen(cwd.ptr);
39 }
40
41 const size_t line = err->line_start + 1;
42 const size_t col = err->column_start + 1;
43 if (use_colors) os_stderr_set_color(TermColorBold);
44
45 // Strip cwd from path
46 if (memStartsWith(pathslice, cwd))
47 fprintf(stderr, ".%c%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": ", ZIG_OS_SEP_CHAR, path+cwd.len, line, col);
48 else
49 fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": ", path, line, col);
50 }
51
52 // Write out the error type
53 switch (err_type) {
54 case ErrTypeError:
55 if (use_colors) os_stderr_set_color(TermColorRed);
56 fprintf(stderr, "error: ");
57 break;
58 case ErrTypeNote:
59 if (use_colors) os_stderr_set_color(TermColorCyan);
60 fprintf(stderr, "note: ");
61 break;
62 default:
63 zig_unreachable();
64 }
65
66 // Write out the error message
67 if (use_colors) os_stderr_set_color(TermColorBold);
68 fputs(buf_ptr(err->msg), stderr);
69 if (use_colors) os_stderr_set_color(TermColorReset);
70 fputc('\n', stderr);
71
72 if (buf_len(&err->line_buf) != 0){
73 // Show the referenced line
74 fprintf(stderr, "%s\n", buf_ptr(&err->line_buf));
75 for (size_t i = 0; i < err->column_start; i += 1) {
76 fprintf(stderr, " ");
77 }
78 // Draw the caret
79 if (use_colors) os_stderr_set_color(TermColorGreen);
80 fprintf(stderr, "^");
81 if (use_colors) os_stderr_set_color(TermColorReset);
82 fprintf(stderr, "\n");
83 }
84
85 for (size_t i = 0; i < err->notes.length; i += 1) {
86 ErrorMsg *note = err->notes.at(i);
87 print_err_msg_type(note, color, ErrTypeNote);
88 }
89}
90
91void print_err_msg(ErrorMsg *err, ErrColor color) {
92 print_err_msg_type(err, color, ErrTypeError);
93}
94
95void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note) {
96 parent->notes.append(note);
97}
98
99ErrorMsg *err_msg_create_with_offset(Buf *path, uint32_t byte_offset, const char *source,
100 Buf *msg)
101{
102 ErrorMsg *err_msg = heap::c_allocator.create<ErrorMsg>();
103 err_msg->path = path;
104 err_msg->msg = msg;
105 err_msg->line_start = 0;
106 err_msg->column_start = 0;
107
108 if (source == nullptr) {
109 // Must initialize the buffer anyway
110 buf_init_from_str(&err_msg->line_buf, "");
111 return err_msg;
112 }
113
114 size_t line_start = 0;
115 size_t i = 0;
116 for (;i < byte_offset; i += 1) {
117 switch (source[i]) {
118 case '\n':
119 err_msg->line_start += 1;
120 err_msg->column_start = 0;
121 line_start = i + 1;
122 continue;
123 default:
124 err_msg->column_start += 1;
125 continue;
126 }
127 }
128 while (source[i] != '\n' && source[i] != 0) {
129 i += 1;
130 }
131
132 buf_init_from_mem(&err_msg->line_buf, source + line_start, i - line_start);
133
134 return err_msg;
135}
src/stage1/errmsg.hpp deleted-30
...@@ -1,30 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_ERRMSG_HPP
9#define ZIG_ERRMSG_HPP
10
11#include "buffer.hpp"
12#include "list.hpp"
13#include "stage1.h"
14
15struct ErrorMsg {
16 size_t line_start;
17 size_t column_start;
18 Buf *msg;
19 Buf *path;
20 Buf line_buf;
21
22 ZigList<ErrorMsg *> notes;
23};
24
25void print_err_msg(ErrorMsg *msg, ErrColor color);
26
27void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note);
28ErrorMsg *err_msg_create_with_offset(Buf *path, uint32_t byte_offset, const char *source, Buf *msg);
29
30#endif
src/stage1/error.cpp deleted-95
...@@ -1,95 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "error.hpp"
9
10const char *err_str(Error err) {
11 switch (err) {
12 case ErrorNone: return "(no error)";
13 case ErrorNoMem: return "out of memory";
14 case ErrorInvalidFormat: return "invalid format";
15 case ErrorSemanticAnalyzeFail: return "semantic analyze failed";
16 case ErrorAccess: return "access denied";
17 case ErrorInterrupted: return "interrupted";
18 case ErrorSystemResources: return "lack of system resources";
19 case ErrorFileNotFound: return "file not found";
20 case ErrorFileSystem: return "file system error";
21 case ErrorFileTooBig: return "file too big";
22 case ErrorDivByZero: return "division by zero";
23 case ErrorOverflow: return "overflow";
24 case ErrorPathAlreadyExists: return "path already exists";
25 case ErrorUnexpected: return "unexpected error";
26 case ErrorExactDivRemainder: return "exact division had a remainder";
27 case ErrorNegativeDenominator: return "negative denominator";
28 case ErrorShiftedOutOneBits: return "exact shift shifted out one bits";
29 case ErrorCCompileErrors: return "C compile errors";
30 case ErrorEndOfFile: return "end of file";
31 case ErrorIsDir: return "is directory";
32 case ErrorNotDir: return "not a directory";
33 case ErrorUnsupportedOperatingSystem: return "unsupported operating system";
34 case ErrorSharingViolation: return "sharing violation";
35 case ErrorPipeBusy: return "pipe busy";
36 case ErrorPrimitiveTypeNotFound: return "primitive type not found";
37 case ErrorCacheUnavailable: return "cache unavailable";
38 case ErrorPathTooLong: return "path too long";
39 case ErrorCCompilerCannotFindFile: return "C compiler cannot find file";
40 case ErrorReadingDepFile: return "failed to read .d file";
41 case ErrorInvalidDepFile: return "invalid .d file";
42 case ErrorMissingArchitecture: return "missing architecture";
43 case ErrorMissingOperatingSystem: return "missing operating system";
44 case ErrorUnknownArchitecture: return "unrecognized architecture";
45 case ErrorUnknownOperatingSystem: return "unrecognized operating system";
46 case ErrorUnknownABI: return "unrecognized C ABI";
47 case ErrorInvalidFilename: return "invalid filename";
48 case ErrorDiskQuota: return "disk space quota exceeded";
49 case ErrorDiskSpace: return "out of disk space";
50 case ErrorUnexpectedWriteFailure: return "unexpected write failure";
51 case ErrorUnexpectedSeekFailure: return "unexpected seek failure";
52 case ErrorUnexpectedFileTruncationFailure: return "unexpected file truncation failure";
53 case ErrorUnimplemented: return "unimplemented";
54 case ErrorOperationAborted: return "operation aborted";
55 case ErrorBrokenPipe: return "broken pipe";
56 case ErrorNoSpaceLeft: return "no space left";
57 case ErrorNoCCompilerInstalled: return "no C compiler installed";
58 case ErrorNotLazy: return "not lazy";
59 case ErrorIsAsync: return "is async";
60 case ErrorImportOutsidePkgPath: return "import of file outside package path";
61 case ErrorUnknownCpu: return "unknown CPU";
62 case ErrorUnknownCpuFeature: return "unknown CPU feature";
63 case ErrorInvalidCpuFeatures: return "invalid CPU features";
64 case ErrorInvalidLlvmCpuFeaturesFormat: return "invalid LLVM CPU features format";
65 case ErrorUnknownApplicationBinaryInterface: return "unknown application binary interface";
66 case ErrorASTUnitFailure: return "compiler bug: clang encountered a compile error, but the libclang API does not expose the error. See https://github.com/ziglang/zig/issues/4455 for more details";
67 case ErrorBadPathName: return "bad path name";
68 case ErrorSymLinkLoop: return "sym link loop";
69 case ErrorProcessFdQuotaExceeded: return "process fd quota exceeded";
70 case ErrorSystemFdQuotaExceeded: return "system fd quota exceeded";
71 case ErrorNoDevice: return "no device";
72 case ErrorDeviceBusy: return "device busy";
73 case ErrorUnableToSpawnCCompiler: return "unable to spawn system C compiler";
74 case ErrorCCompilerExitCode: return "system C compiler exited with failure code";
75 case ErrorCCompilerCrashed: return "system C compiler crashed";
76 case ErrorCCompilerCannotFindHeaders: return "system C compiler cannot find libc headers";
77 case ErrorLibCRuntimeNotFound: return "libc runtime not found";
78 case ErrorLibCStdLibHeaderNotFound: return "libc std lib headers not found";
79 case ErrorLibCKernel32LibNotFound: return "kernel32 library not found";
80 case ErrorUnsupportedArchitecture: return "unsupported architecture";
81 case ErrorWindowsSdkNotFound: return "Windows SDK not found";
82 case ErrorUnknownDynamicLinkerPath: return "unknown dynamic linker path";
83 case ErrorTargetHasNoDynamicLinker: return "target has no dynamic linker";
84 case ErrorInvalidAbiVersion: return "invalid C ABI version";
85 case ErrorInvalidOperatingSystemVersion: return "invalid operating system version";
86 case ErrorUnknownClangOption: return "unknown Clang option";
87 case ErrorNestedResponseFile: return "nested response file";
88 case ErrorZigIsTheCCompiler: return "Zig was not provided with libc installation information, and so it does not know where the libc paths are on the system. Zig attempted to use the system C compiler to find out where the libc paths are, but discovered that Zig is being used as the system C compiler.";
89 case ErrorFileBusy: return "file is busy";
90 case ErrorLocked: return "file is locked by another process";
91 case ErrorInvalidCharacter: return "invalid character";
92 case ErrorUnicodePointTooLarge: return "unicode codepoint too large";
93 }
94 return "(invalid error)";
95}
src/stage1/error.hpp deleted-17
...@@ -1,17 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ERROR_HPP
9#define ERROR_HPP
10
11#include "stage2.h"
12
13const char *err_str(Error err);
14
15#define assertNoError(err) assert((err) == ErrorNone);
16
17#endif
src/stage1/hash_map.hpp deleted-446
...@@ -1,446 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_HASH_MAP_HPP
9#define ZIG_HASH_MAP_HPP
10
11#include "util.hpp"
12
13#include <stdint.h>
14
15template<typename K>
16struct MakePointer {
17 typedef K const *Type;
18 static Type convert(K const &val) {
19 return &val;
20 }
21};
22
23template<typename K>
24struct MakePointer<K*> {
25 typedef K *Type;
26 static Type convert(K * const &val) {
27 return val;
28 }
29};
30
31template<typename K>
32struct MakePointer<K const *> {
33 typedef K const *Type;
34 static Type convert(K const * const &val) {
35 return val;
36 }
37};
38
39template<typename K, typename V,
40 uint32_t (*HashFunction)(typename MakePointer<K>::Type key),
41 bool (*EqualFn)(typename MakePointer<K>::Type a, typename MakePointer<K>::Type b)>
42class HashMap {
43public:
44 void init(int capacity) {
45 init_capacity(capacity);
46 }
47 void deinit(void) {
48 _entries.deinit();
49 heap::c_allocator.deallocate(_index_bytes,
50 _indexes_len * capacity_index_size(_indexes_len));
51 }
52
53 struct Entry {
54 uint32_t hash;
55 uint32_t distance_from_start_index;
56 K key;
57 V value;
58 };
59
60 void clear() {
61 _entries.clear();
62 memset(_index_bytes, 0, _indexes_len * capacity_index_size(_indexes_len));
63 _max_distance_from_start_index = 0;
64 _modification_count += 1;
65 }
66
67 size_t size() const {
68 return _entries.length;
69 }
70
71 void put(const K &key, const V &value) {
72 _modification_count += 1;
73
74 // This allows us to take a pointer to an entry in `internal_put` which
75 // will not become a dead pointer when the array list is appended.
76 _entries.ensure_capacity(_entries.length + 1);
77
78 if (_index_bytes == nullptr) {
79 if (_entries.length < 16) {
80 _entries.append({HashFunction(MakePointer<K>::convert(key)), 0, key, value});
81 return;
82 } else {
83 _indexes_len = 32;
84 _index_bytes = heap::c_allocator.allocate<uint8_t>(_indexes_len);
85 _max_distance_from_start_index = 0;
86 for (size_t i = 0; i < _entries.length; i += 1) {
87 Entry *entry = &_entries.items[i];
88 put_index(entry, i, _index_bytes);
89 }
90 return internal_put(key, value, _index_bytes);
91 }
92 }
93
94 // if we would get too full (60%), double the indexes size
95 if ((_entries.length + 1) * 5 >= _indexes_len * 3) {
96 heap::c_allocator.deallocate(_index_bytes,
97 _indexes_len * capacity_index_size(_indexes_len));
98 _indexes_len *= 2;
99 size_t sz = capacity_index_size(_indexes_len);
100 // This zero initializes the bytes, setting them all empty.
101 _index_bytes = heap::c_allocator.allocate<uint8_t>(_indexes_len * sz);
102 _max_distance_from_start_index = 0;
103 for (size_t i = 0; i < _entries.length; i += 1) {
104 Entry *entry = &_entries.items[i];
105 switch (sz) {
106 case 1:
107 put_index(entry, i, (uint8_t*)_index_bytes);
108 continue;
109 case 2:
110 put_index(entry, i, (uint16_t*)_index_bytes);
111 continue;
112 case 4:
113 put_index(entry, i, (uint32_t*)_index_bytes);
114 continue;
115 default:
116 put_index(entry, i, (size_t*)_index_bytes);
117 continue;
118 }
119 }
120 }
121
122 switch (capacity_index_size(_indexes_len)) {
123 case 1: return internal_put(key, value, (uint8_t*)_index_bytes);
124 case 2: return internal_put(key, value, (uint16_t*)_index_bytes);
125 case 4: return internal_put(key, value, (uint32_t*)_index_bytes);
126 default: return internal_put(key, value, (size_t*)_index_bytes);
127 }
128 }
129
130 Entry *put_unique(const K &key, const V &value) {
131 // TODO make this more efficient
132 Entry *entry = internal_get(key);
133 if (entry)
134 return entry;
135 put(key, value);
136 return nullptr;
137 }
138
139 const V &get(const K &key) const {
140 Entry *entry = internal_get(key);
141 if (!entry)
142 zig_panic("key not found");
143 return entry->value;
144 }
145
146 Entry *maybe_get(const K &key) const {
147 return internal_get(key);
148 }
149
150 bool remove(const K &key) {
151 bool deleted_something = maybe_remove(key);
152 if (!deleted_something)
153 zig_panic("key not found");
154 return deleted_something;
155 }
156
157 bool maybe_remove(const K &key) {
158 _modification_count += 1;
159 if (_index_bytes == nullptr) {
160 uint32_t hash = HashFunction(MakePointer<K>::convert(key));
161 for (size_t i = 0; i < _entries.length; i += 1) {
162 if (_entries.items[i].hash == hash && EqualFn(MakePointer<K>::convert(_entries.items[i].key), MakePointer<K>::convert(key))) {
163 _entries.swap_remove(i);
164 return true;
165 }
166 }
167 return false;
168 }
169 switch (capacity_index_size(_indexes_len)) {
170 case 1: return internal_remove(key, (uint8_t*)_index_bytes);
171 case 2: return internal_remove(key, (uint16_t*)_index_bytes);
172 case 4: return internal_remove(key, (uint32_t*)_index_bytes);
173 default: return internal_remove(key, (size_t*)_index_bytes);
174 }
175 }
176
177 class Iterator {
178 public:
179 Entry *next() {
180 if (_inital_modification_count != _table->_modification_count)
181 zig_panic("concurrent modification");
182 if (_index >= _table->_entries.length)
183 return nullptr;
184 Entry *entry = &_table->_entries.items[_index];
185 _index += 1;
186 return entry;
187 }
188 private:
189 const HashMap * _table;
190 // iterator through the entry array
191 size_t _index = 0;
192 // used to detect concurrent modification
193 uint32_t _inital_modification_count;
194 Iterator(const HashMap * table) :
195 _table(table), _inital_modification_count(table->_modification_count) {
196 }
197 friend HashMap;
198 };
199
200 // you must not modify the underlying HashMap while this iterator is still in use
201 Iterator entry_iterator() const {
202 return Iterator(this);
203 }
204
205private:
206 // Maintains insertion order.
207 ZigList<Entry> _entries;
208 // If _indexes_len is less than 2**8, this is an array of uint8_t.
209 // If _indexes_len is less than 2**16, it is an array of uint16_t.
210 // If _indexes_len is less than 2**32, it is an array of uint32_t.
211 // Otherwise it is size_t.
212 // It's off by 1. 0 means empty slot, 1 means index 0, etc.
213 uint8_t *_index_bytes;
214 // This is the number of indexes. When indexes are bytes, it equals number of bytes.
215 // When indexes are uint16_t, _indexes_len is half the number of bytes.
216 size_t _indexes_len;
217
218 size_t _max_distance_from_start_index;
219 // This is used to detect bugs where a hashtable is edited while an iterator is running.
220 uint32_t _modification_count;
221
222 void init_capacity(size_t capacity) {
223 _entries = {};
224 _entries.ensure_capacity(capacity);
225 _indexes_len = 0;
226 if (capacity >= 16) {
227 // So that at capacity it will only be 60% full.
228 _indexes_len = capacity * 5 / 3;
229 size_t sz = capacity_index_size(_indexes_len);
230 // This zero initializes _index_bytes which sets them all to empty.
231 _index_bytes = heap::c_allocator.allocate<uint8_t>(_indexes_len * sz);
232 } else {
233 _index_bytes = nullptr;
234 }
235
236 _max_distance_from_start_index = 0;
237 _modification_count = 0;
238 }
239
240 static size_t capacity_index_size(size_t len) {
241 if (len < UINT8_MAX)
242 return 1;
243 if (len < UINT16_MAX)
244 return 2;
245 if (len < UINT32_MAX)
246 return 4;
247 return sizeof(size_t);
248 }
249
250 template <typename I>
251 void internal_put(const K &key, const V &value, I *indexes) {
252 uint32_t hash = HashFunction(MakePointer<K>::convert(key));
253 uint32_t distance_from_start_index = 0;
254 size_t start_index = hash_to_index(hash);
255 for (size_t roll_over = 0; roll_over < _indexes_len;
256 roll_over += 1, distance_from_start_index += 1)
257 {
258 size_t index_index = (start_index + roll_over) % _indexes_len;
259 I index_data = indexes[index_index];
260 if (index_data == 0) {
261 _entries.append_assuming_capacity({ hash, distance_from_start_index, key, value });
262 indexes[index_index] = _entries.length;
263 if (distance_from_start_index > _max_distance_from_start_index)
264 _max_distance_from_start_index = distance_from_start_index;
265 return;
266 }
267 // This pointer survives the following append because we call
268 // _entries.ensure_capacity before internal_put.
269 Entry *entry = &_entries.items[index_data - 1];
270 if (entry->hash == hash && EqualFn(MakePointer<K>::convert(entry->key), MakePointer<K>::convert(key))) {
271 *entry = {hash, distance_from_start_index, key, value};
272 if (distance_from_start_index > _max_distance_from_start_index)
273 _max_distance_from_start_index = distance_from_start_index;
274 return;
275 }
276 if (entry->distance_from_start_index < distance_from_start_index) {
277 // In this case, we did not find the item. We will put a new entry.
278 // However, we will use this index for the new entry, and move
279 // the previous index down the line, to keep the _max_distance_from_start_index
280 // as small as possible.
281 _entries.append_assuming_capacity({ hash, distance_from_start_index, key, value });
282 indexes[index_index] = _entries.length;
283 if (distance_from_start_index > _max_distance_from_start_index)
284 _max_distance_from_start_index = distance_from_start_index;
285
286 distance_from_start_index = entry->distance_from_start_index;
287
288 // Find somewhere to put the index we replaced by shifting
289 // following indexes backwards.
290 roll_over += 1;
291 distance_from_start_index += 1;
292 for (; roll_over < _indexes_len; roll_over += 1, distance_from_start_index += 1) {
293 size_t index_index = (start_index + roll_over) % _indexes_len;
294 I next_index_data = indexes[index_index];
295 if (next_index_data == 0) {
296 if (distance_from_start_index > _max_distance_from_start_index)
297 _max_distance_from_start_index = distance_from_start_index;
298 entry->distance_from_start_index = distance_from_start_index;
299 indexes[index_index] = index_data;
300 return;
301 }
302 Entry *next_entry = &_entries.items[next_index_data - 1];
303 if (next_entry->distance_from_start_index < distance_from_start_index) {
304 if (distance_from_start_index > _max_distance_from_start_index)
305 _max_distance_from_start_index = distance_from_start_index;
306 entry->distance_from_start_index = distance_from_start_index;
307 indexes[index_index] = index_data;
308 distance_from_start_index = next_entry->distance_from_start_index;
309 entry = next_entry;
310 index_data = next_index_data;
311 }
312 }
313 zig_unreachable();
314 }
315 }
316 zig_unreachable();
317 }
318
319 template <typename I>
320 void put_index(Entry *entry, size_t entry_index, I *indexes) {
321 size_t start_index = hash_to_index(entry->hash);
322 size_t index_data = entry_index + 1;
323 for (size_t roll_over = 0, distance_from_start_index = 0;
324 roll_over < _indexes_len; roll_over += 1, distance_from_start_index += 1)
325 {
326 size_t index_index = (start_index + roll_over) % _indexes_len;
327 size_t next_index_data = indexes[index_index];
328 if (next_index_data == 0) {
329 if (distance_from_start_index > _max_distance_from_start_index)
330 _max_distance_from_start_index = distance_from_start_index;
331 entry->distance_from_start_index = distance_from_start_index;
332 indexes[index_index] = index_data;
333 return;
334 }
335 Entry *next_entry = &_entries.items[next_index_data - 1];
336 if (next_entry->distance_from_start_index < distance_from_start_index) {
337 if (distance_from_start_index > _max_distance_from_start_index)
338 _max_distance_from_start_index = distance_from_start_index;
339 entry->distance_from_start_index = distance_from_start_index;
340 indexes[index_index] = index_data;
341 distance_from_start_index = next_entry->distance_from_start_index;
342 entry = next_entry;
343 index_data = next_index_data;
344 }
345 }
346 zig_unreachable();
347 }
348
349 Entry *internal_get(const K &key) const {
350 if (_index_bytes == nullptr) {
351 uint32_t hash = HashFunction(MakePointer<K>::convert(key));
352 for (size_t i = 0; i < _entries.length; i += 1) {
353 if (_entries.items[i].hash == hash && EqualFn(MakePointer<K>::convert(_entries.items[i].key), MakePointer<K>::convert(key))) {
354 return &_entries.items[i];
355 }
356 }
357 return nullptr;
358 }
359 switch (capacity_index_size(_indexes_len)) {
360 case 1: return internal_get2(key, (uint8_t*)_index_bytes);
361 case 2: return internal_get2(key, (uint16_t*)_index_bytes);
362 case 4: return internal_get2(key, (uint32_t*)_index_bytes);
363 default: return internal_get2(key, (size_t*)_index_bytes);
364 }
365 }
366
367 template <typename I>
368 Entry *internal_get2(const K &key, I *indexes) const {
369 uint32_t hash = HashFunction(MakePointer<K>::convert(key));
370 size_t start_index = hash_to_index(hash);
371 for (size_t roll_over = 0; roll_over <= _max_distance_from_start_index; roll_over += 1) {
372 size_t index_index = (start_index + roll_over) % _indexes_len;
373 size_t index_data = indexes[index_index];
374 if (index_data == 0)
375 return nullptr;
376
377 Entry *entry = &_entries.items[index_data - 1];
378 if (entry->hash == hash && EqualFn(MakePointer<K>::convert(entry->key), MakePointer<K>::convert(key)))
379 return entry;
380 }
381 return nullptr;
382 }
383
384 size_t hash_to_index(uint32_t hash) const {
385 return ((size_t)hash) % _indexes_len;
386 }
387
388 template <typename I>
389 bool internal_remove(const K &key, I *indexes) {
390 uint32_t hash = HashFunction(MakePointer<K>::convert(key));
391 size_t start_index = hash_to_index(hash);
392 for (size_t roll_over = 0; roll_over <= _max_distance_from_start_index; roll_over += 1) {
393 size_t index_index = (start_index + roll_over) % _indexes_len;
394 size_t index_data = indexes[index_index];
395 if (index_data == 0)
396 return false;
397
398 size_t index = index_data - 1;
399 Entry *entry = &_entries.items[index];
400 if (entry->hash != hash || !EqualFn(MakePointer<K>::convert(entry->key), MakePointer<K>::convert(key)))
401 continue;
402
403 size_t prev_index = index_index;
404 _entries.swap_remove(index);
405 if (_entries.length > 0 && _entries.length != index) {
406 // Because of the swap remove, now we need to update the index that was
407 // pointing to the last entry and is now pointing to this removed item slot.
408 update_entry_index(_entries.length, index, indexes);
409 }
410
411 // Now we have to shift over the following indexes.
412 roll_over += 1;
413 for (; roll_over < _indexes_len; roll_over += 1) {
414 size_t next_index = (start_index + roll_over) % _indexes_len;
415 if (indexes[next_index] == 0) {
416 indexes[prev_index] = 0;
417 return true;
418 }
419 Entry *next_entry = &_entries.items[indexes[next_index] - 1];
420 if (next_entry->distance_from_start_index == 0) {
421 indexes[prev_index] = 0;
422 return true;
423 }
424 indexes[prev_index] = indexes[next_index];
425 prev_index = next_index;
426 next_entry->distance_from_start_index -= 1;
427 }
428 zig_unreachable();
429 }
430 return false;
431 }
432
433 template <typename I>
434 void update_entry_index(size_t old_entry_index, size_t new_entry_index, I *indexes) {
435 size_t start_index = hash_to_index(_entries.items[new_entry_index].hash);
436 for (size_t roll_over = 0; roll_over <= _max_distance_from_start_index; roll_over += 1) {
437 size_t index_index = (start_index + roll_over) % _indexes_len;
438 if (indexes[index_index] == old_entry_index + 1) {
439 indexes[index_index] = new_entry_index + 1;
440 return;
441 }
442 }
443 zig_unreachable();
444 }
445};
446#endif
src/stage1/heap.cpp deleted-314
...@@ -1,314 +0,0 @@
1/*
2 * Copyright (c) 2020 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include <new>
9#include <string.h>
10
11#include "heap.hpp"
12
13namespace heap {
14
15extern mem::Allocator &bootstrap_allocator;
16
17//
18// BootstrapAllocator implementation is identical to CAllocator minus
19// profile profile functionality. Splitting off to a base interface doesn't
20// seem worthwhile.
21//
22
23void BootstrapAllocator::init(const char *name) {}
24void BootstrapAllocator::deinit() {}
25
26void *BootstrapAllocator::internal_allocate(const mem::TypeInfo &info, size_t count) {
27 return mem::os::calloc(count, info.size);
28}
29
30void *BootstrapAllocator::internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) {
31 return mem::os::malloc(count * info.size);
32}
33
34void *BootstrapAllocator::internal_reallocate(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) {
35 auto new_ptr = this->internal_reallocate_nonzero(info, old_ptr, old_count, new_count);
36 if (new_count > old_count)
37 memset(reinterpret_cast<uint8_t *>(new_ptr) + (old_count * info.size), 0, (new_count - old_count) * info.size);
38 return new_ptr;
39}
40
41void *BootstrapAllocator::internal_reallocate_nonzero(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) {
42 return mem::os::realloc(old_ptr, new_count * info.size);
43}
44
45void BootstrapAllocator::internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) {
46 mem::os::free(ptr);
47}
48
49void CAllocator::init(const char *name) { }
50
51void CAllocator::deinit() { }
52
53CAllocator *CAllocator::construct(mem::Allocator *allocator, const char *name) {
54 auto p = new(allocator->create<CAllocator>()) CAllocator();
55 p->init(name);
56 return p;
57}
58
59void CAllocator::destruct(mem::Allocator *allocator) {
60 this->deinit();
61 allocator->destroy(this);
62}
63
64void *CAllocator::internal_allocate(const mem::TypeInfo &info, size_t count) {
65 return mem::os::calloc(count, info.size);
66}
67
68void *CAllocator::internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) {
69 return mem::os::malloc(count * info.size);
70}
71
72void *CAllocator::internal_reallocate(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) {
73 auto new_ptr = this->internal_reallocate_nonzero(info, old_ptr, old_count, new_count);
74 if (new_count > old_count)
75 memset(reinterpret_cast<uint8_t *>(new_ptr) + (old_count * info.size), 0, (new_count - old_count) * info.size);
76 return new_ptr;
77}
78
79void *CAllocator::internal_reallocate_nonzero(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) {
80 return mem::os::realloc(old_ptr, new_count * info.size);
81}
82
83void CAllocator::internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) {
84 mem::os::free(ptr);
85}
86
87struct ArenaAllocator::Impl {
88 Allocator *backing;
89
90 // regular allocations bump through a segment of static size
91 struct Segment {
92 static constexpr size_t size = 65536;
93 static constexpr size_t object_threshold = 4096;
94
95 uint8_t data[size];
96 };
97
98 // active segment
99 Segment *segment;
100 size_t segment_offset;
101
102 // keep track of segments
103 struct SegmentTrack {
104 static constexpr size_t size = (4096 - sizeof(SegmentTrack *)) / sizeof(Segment *);
105
106 // null if first
107 SegmentTrack *prev;
108 Segment *segments[size];
109 };
110 static_assert(sizeof(SegmentTrack) <= 4096, "unwanted struct padding");
111
112 // active segment track
113 SegmentTrack *segment_track;
114 size_t segment_track_remain;
115
116 // individual allocations punted to backing allocator
117 struct Object {
118 uint8_t *ptr;
119 size_t len;
120 };
121
122 // keep track of objects
123 struct ObjectTrack {
124 static constexpr size_t size = (4096 - sizeof(ObjectTrack *)) / sizeof(Object);
125
126 // null if first
127 ObjectTrack *prev;
128 Object objects[size];
129 };
130 static_assert(sizeof(ObjectTrack) <= 4096, "unwanted struct padding");
131
132 // active object track
133 ObjectTrack *object_track;
134 size_t object_track_remain;
135
136 ATTRIBUTE_RETURNS_NOALIAS inline void *allocate(const mem::TypeInfo& info, size_t count);
137 inline void *reallocate(const mem::TypeInfo& info, void *old_ptr, size_t old_count, size_t new_count);
138
139 inline void new_segment();
140 inline void track_segment();
141 inline void track_object(Object object);
142};
143
144void *ArenaAllocator::Impl::allocate(const mem::TypeInfo& info, size_t count) {
145#ifndef NDEBUG
146 // make behavior when size == 0 portable
147 if (info.size == 0 || count == 0)
148 return nullptr;
149#endif
150 const size_t nbytes = info.size * count;
151 this->segment_offset = (this->segment_offset + (info.alignment - 1)) & ~(info.alignment - 1);
152 if (nbytes >= Segment::object_threshold) {
153 auto ptr = this->backing->allocate<uint8_t>(nbytes);
154 this->track_object({ptr, nbytes});
155 return ptr;
156 }
157 if (this->segment_offset + nbytes > Segment::size)
158 this->new_segment();
159 auto ptr = &this->segment->data[this->segment_offset];
160 this->segment_offset += nbytes;
161 return ptr;
162}
163
164void *ArenaAllocator::Impl::reallocate(const mem::TypeInfo& info, void *old_ptr, size_t old_count, size_t new_count) {
165#ifndef NDEBUG
166 // make behavior when size == 0 portable
167 if (info.size == 0 && old_ptr == nullptr)
168 return nullptr;
169#endif
170 const size_t new_nbytes = info.size * new_count;
171 if (new_nbytes <= info.size * old_count)
172 return old_ptr;
173 const size_t old_nbytes = info.size * old_count;
174 this->segment_offset = (this->segment_offset + (info.alignment - 1)) & ~(info.alignment - 1);
175 if (new_nbytes >= Segment::object_threshold) {
176 auto new_ptr = this->backing->allocate<uint8_t>(new_nbytes);
177 this->track_object({new_ptr, new_nbytes});
178 memcpy(new_ptr, old_ptr, old_nbytes);
179 return new_ptr;
180 }
181 if (this->segment_offset + new_nbytes > Segment::size)
182 this->new_segment();
183 auto new_ptr = &this->segment->data[this->segment_offset];
184 this->segment_offset += new_nbytes;
185 memcpy(new_ptr, old_ptr, old_nbytes);
186 return new_ptr;
187}
188
189void ArenaAllocator::Impl::new_segment() {
190 this->segment = this->backing->create<Segment>();
191 this->segment_offset = 0;
192 this->track_segment();
193}
194
195void ArenaAllocator::Impl::track_segment() {
196 assert(this->segment != nullptr);
197 if (this->segment_track_remain < 1) {
198 auto prev = this->segment_track;
199 this->segment_track = this->backing->create<SegmentTrack>();
200 this->segment_track->prev = prev;
201 this->segment_track_remain = SegmentTrack::size;
202 }
203 this->segment_track_remain -= 1;
204 this->segment_track->segments[this->segment_track_remain] = this->segment;
205}
206
207void ArenaAllocator::Impl::track_object(Object object) {
208 if (this->object_track_remain < 1) {
209 auto prev = this->object_track;
210 this->object_track = this->backing->create<ObjectTrack>();
211 this->object_track->prev = prev;
212 this->object_track_remain = ObjectTrack::size;
213 }
214 this->object_track_remain -= 1;
215 this->object_track->objects[this->object_track_remain] = object;
216}
217
218void ArenaAllocator::init(Allocator *backing, const char *name) {
219 this->impl = bootstrap_allocator.create<Impl>();
220 {
221 auto &r = *this->impl;
222 r.backing = backing;
223 r.segment_offset = Impl::Segment::size;
224 }
225}
226
227void ArenaAllocator::deinit() {
228 auto &backing = *this->impl->backing;
229
230 // segments
231 if (this->impl->segment_track) {
232 // active track is not full and bounded by track_remain
233 auto prev = this->impl->segment_track->prev;
234 {
235 auto t = this->impl->segment_track;
236 for (size_t i = this->impl->segment_track_remain; i < Impl::SegmentTrack::size; ++i)
237 backing.destroy(t->segments[i]);
238 backing.destroy(t);
239 }
240
241 // previous tracks are full
242 for (auto t = prev; t != nullptr;) {
243 for (size_t i = 0; i < Impl::SegmentTrack::size; ++i)
244 backing.destroy(t->segments[i]);
245 prev = t->prev;
246 backing.destroy(t);
247 t = prev;
248 }
249 }
250
251 // objects
252 if (this->impl->object_track) {
253 // active track is not full and bounded by track_remain
254 auto prev = this->impl->object_track->prev;
255 {
256 auto t = this->impl->object_track;
257 for (size_t i = this->impl->object_track_remain; i < Impl::ObjectTrack::size; ++i) {
258 auto &obj = t->objects[i];
259 backing.deallocate(obj.ptr, obj.len);
260 }
261 backing.destroy(t);
262 }
263
264 // previous tracks are full
265 for (auto t = prev; t != nullptr;) {
266 for (size_t i = 0; i < Impl::ObjectTrack::size; ++i) {
267 auto &obj = t->objects[i];
268 backing.deallocate(obj.ptr, obj.len);
269 }
270 prev = t->prev;
271 backing.destroy(t);
272 t = prev;
273 }
274 }
275}
276
277ArenaAllocator *ArenaAllocator::construct(mem::Allocator *allocator, mem::Allocator *backing, const char *name) {
278 auto p = new(allocator->create<ArenaAllocator>()) ArenaAllocator;
279 p->init(backing, name);
280 return p;
281}
282
283void ArenaAllocator::destruct(mem::Allocator *allocator) {
284 this->deinit();
285 allocator->destroy(this);
286}
287
288void *ArenaAllocator::internal_allocate(const mem::TypeInfo &info, size_t count) {
289 return this->impl->allocate(info, count);
290}
291
292void *ArenaAllocator::internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) {
293 return this->impl->allocate(info, count);
294}
295
296void *ArenaAllocator::internal_reallocate(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) {
297 return this->internal_reallocate_nonzero(info, old_ptr, old_count, new_count);
298}
299
300void *ArenaAllocator::internal_reallocate_nonzero(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) {
301 return this->impl->reallocate(info, old_ptr, old_count, new_count);
302}
303
304void ArenaAllocator::internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) {
305 // noop
306}
307
308BootstrapAllocator bootstrap_allocator_state;
309mem::Allocator &bootstrap_allocator = bootstrap_allocator_state;
310
311CAllocator c_allocator_state;
312mem::Allocator &c_allocator = c_allocator_state;
313
314} // namespace heap
src/stage1/heap.hpp deleted-81
...@@ -1,81 +0,0 @@
1/*
2 * Copyright (c) 2020 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_HEAP_HPP
9#define ZIG_HEAP_HPP
10
11#include "util_base.hpp"
12#include "mem.hpp"
13
14namespace heap {
15
16struct BootstrapAllocator final : mem::Allocator {
17 void init(const char *name);
18 void deinit();
19 void destruct(Allocator *allocator) {}
20
21private:
22 ATTRIBUTE_RETURNS_NOALIAS void *internal_allocate(const mem::TypeInfo &info, size_t count) final;
23 ATTRIBUTE_RETURNS_NOALIAS void *internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) final;
24 void *internal_reallocate(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) final;
25 void *internal_reallocate_nonzero(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) final;
26 void internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) final;
27};
28
29struct CAllocator final : mem::Allocator {
30 void init(const char *name);
31 void deinit();
32
33 static CAllocator *construct(mem::Allocator *allocator, const char *name);
34 void destruct(mem::Allocator *allocator) final;
35
36
37private:
38 ATTRIBUTE_RETURNS_NOALIAS void *internal_allocate(const mem::TypeInfo &info, size_t count) final;
39 ATTRIBUTE_RETURNS_NOALIAS void *internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) final;
40 void *internal_reallocate(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) final;
41 void *internal_reallocate_nonzero(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) final;
42 void internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) final;
43
44};
45
46//
47// arena allocator
48//
49// - allocations are backed by the underlying allocator's memory
50// - allocations are N:1 relationship to underlying allocations
51// - dellocations are noops
52// - deinit() releases all underlying memory
53//
54struct ArenaAllocator final : mem::Allocator {
55 void init(Allocator *backing, const char *name);
56 void deinit();
57
58 static ArenaAllocator *construct(mem::Allocator *allocator, mem::Allocator *backing, const char *name);
59 void destruct(mem::Allocator *allocator) final;
60
61
62private:
63 ATTRIBUTE_RETURNS_NOALIAS void *internal_allocate(const mem::TypeInfo &info, size_t count) final;
64 ATTRIBUTE_RETURNS_NOALIAS void *internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) final;
65 void *internal_reallocate(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) final;
66 void *internal_reallocate_nonzero(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) final;
67 void internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) final;
68
69 struct Impl;
70 Impl *impl;
71};
72
73extern BootstrapAllocator bootstrap_allocator_state;
74extern mem::Allocator &bootstrap_allocator;
75
76extern CAllocator c_allocator_state;
77extern mem::Allocator &c_allocator;
78
79} // namespace heap
80
81#endif
src/stage1/ir.cpp deleted-26627
...@@ -1,26627 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "astgen.hpp"
9#include "analyze.hpp"
10#include "error.hpp"
11#include "ir.hpp"
12#include "ir_print.hpp"
13#include "os.hpp"
14#include "range_set.hpp"
15#include "softfloat.hpp"
16#include "softfloat_ext.hpp"
17#include "util.hpp"
18#include "mem_list.hpp"
19#include "all_types.hpp"
20#include "zigendian.h"
21
22#include <errno.h>
23#include <math.h>
24
25struct IrBuilderGen {
26 CodeGen *codegen;
27 Stage1Air *exec;
28 Stage1AirBasicBlock *current_basic_block;
29
30 // track for immediate post-analysis destruction
31 mem::List<Stage1AirInstConst *> constants;
32};
33
34struct IrAnalyze {
35 CodeGen *codegen;
36 Stage1Zir *zir;
37 Stage1ZirBasicBlock *zir_current_basic_block;
38 IrBuilderGen new_irb;
39 size_t old_bb_index;
40 size_t instruction_index;
41 ZigType *explicit_return_type;
42 AstNode *explicit_return_type_source_node;
43 ZigList<Stage1AirInst *> src_implicit_return_type_list;
44 ZigList<IrSuspendPosition> resume_stack;
45 Stage1ZirBasicBlock *const_predecessor_bb;
46 size_t ref_count;
47 size_t break_debug_id; // for debugging purposes
48 Stage1AirInst *return_ptr;
49 Stage1Air *parent_exec;
50 size_t *backward_branch_count;
51 size_t *backward_branch_quota;
52 ZigFn *fn;
53 Stage1ZirInst *suspend_source_instr;
54
55 // For the purpose of using in a debugger
56 void dump();
57};
58
59enum ConstCastResultId {
60 ConstCastResultIdOk,
61 ConstCastResultIdInvalid,
62 ConstCastResultIdErrSet,
63 ConstCastResultIdErrSetGlobal,
64 ConstCastResultIdPointerChild,
65 ConstCastResultIdSliceChild,
66 ConstCastResultIdOptionalChild,
67 ConstCastResultIdOptionalShape,
68 ConstCastResultIdErrorUnionPayload,
69 ConstCastResultIdErrorUnionErrorSet,
70 ConstCastResultIdFnAlign,
71 ConstCastResultIdFnCC,
72 ConstCastResultIdFnVarArgs,
73 ConstCastResultIdFnIsGeneric,
74 ConstCastResultIdFnReturnType,
75 ConstCastResultIdFnArgCount,
76 ConstCastResultIdFnGenericArgCount,
77 ConstCastResultIdFnArg,
78 ConstCastResultIdFnArgNoAlias,
79 ConstCastResultIdType,
80 ConstCastResultIdUnresolvedInferredErrSet,
81 ConstCastResultIdAsyncAllocatorType,
82 ConstCastResultIdBadAllowsZero,
83 ConstCastResultIdArrayChild,
84 ConstCastResultIdSentinelArrays,
85 ConstCastResultIdPtrLens,
86 ConstCastResultIdCV,
87 ConstCastResultIdPtrSentinel,
88 ConstCastResultIdIntShorten,
89 ConstCastResultIdVectorLength,
90 ConstCastResultIdVectorChild,
91};
92
93struct ConstCastOnly;
94struct ConstCastArg {
95 size_t arg_index;
96 ZigType *actual_param_type;
97 ZigType *expected_param_type;
98 ConstCastOnly *child;
99};
100
101struct ConstCastArgNoAlias {
102 size_t arg_index;
103};
104
105struct ConstCastOptionalMismatch;
106struct ConstCastPointerMismatch;
107struct ConstCastSliceMismatch;
108struct ConstCastErrUnionErrSetMismatch;
109struct ConstCastErrUnionPayloadMismatch;
110struct ConstCastErrSetMismatch;
111struct ConstCastTypeMismatch;
112struct ConstCastArrayMismatch;
113struct ConstCastBadAllowsZero;
114struct ConstCastBadNullTermArrays;
115struct ConstCastBadCV;
116struct ConstCastPtrSentinel;
117struct ConstCastIntShorten;
118
119struct ConstCastOnly {
120 ConstCastResultId id;
121 union {
122 ConstCastErrSetMismatch *error_set_mismatch;
123 ConstCastPointerMismatch *pointer_mismatch;
124 ConstCastSliceMismatch *slice_mismatch;
125 ConstCastOptionalMismatch *optional;
126 ConstCastErrUnionPayloadMismatch *error_union_payload;
127 ConstCastErrUnionErrSetMismatch *error_union_error_set;
128 ConstCastTypeMismatch *type_mismatch;
129 ConstCastArrayMismatch *array_mismatch;
130 ConstCastOnly *return_type;
131 ConstCastOnly *null_wrap_ptr_child;
132 ConstCastArg fn_arg;
133 ConstCastArgNoAlias arg_no_alias;
134 ConstCastBadAllowsZero *bad_allows_zero;
135 ConstCastBadNullTermArrays *sentinel_arrays;
136 ConstCastBadCV *bad_cv;
137 ConstCastPtrSentinel *bad_ptr_sentinel;
138 ConstCastIntShorten *int_shorten;
139 } data;
140};
141
142struct ConstCastTypeMismatch {
143 ZigType *wanted_type;
144 ZigType *actual_type;
145};
146
147struct ConstCastOptionalMismatch {
148 ConstCastOnly child;
149 ZigType *wanted_child;
150 ZigType *actual_child;
151};
152
153struct ConstCastPointerMismatch {
154 ConstCastOnly child;
155 ZigType *wanted_child;
156 ZigType *actual_child;
157};
158
159struct ConstCastSliceMismatch {
160 ConstCastOnly child;
161 ZigType *wanted_child;
162 ZigType *actual_child;
163};
164
165struct ConstCastArrayMismatch {
166 ConstCastOnly child;
167 ZigType *wanted_child;
168 ZigType *actual_child;
169};
170
171struct ConstCastErrUnionErrSetMismatch {
172 ConstCastOnly child;
173 ZigType *wanted_err_set;
174 ZigType *actual_err_set;
175};
176
177struct ConstCastErrUnionPayloadMismatch {
178 ConstCastOnly child;
179 ZigType *wanted_payload;
180 ZigType *actual_payload;
181};
182
183struct ConstCastErrSetMismatch {
184 ZigList<ErrorTableEntry *> missing_errors;
185};
186
187struct ConstCastBadAllowsZero {
188 ZigType *wanted_type;
189 ZigType *actual_type;
190};
191
192struct ConstCastBadNullTermArrays {
193 ConstCastOnly child;
194 ZigType *wanted_type;
195 ZigType *actual_type;
196};
197
198struct ConstCastBadCV {
199 ZigType *wanted_type;
200 ZigType *actual_type;
201};
202
203struct ConstCastPtrSentinel {
204 ZigType *wanted_type;
205 ZigType *actual_type;
206};
207
208struct ConstCastIntShorten {
209 ZigType *wanted_type;
210 ZigType *actual_type;
211};
212
213// for debugging purposes
214struct DbgIrBreakPoint {
215 const char *src_file;
216 uint32_t line;
217};
218
219static Stage1AirInst *ir_implicit_cast(IrAnalyze *ira, Stage1AirInst *value, ZigType *expected_type);
220static Stage1AirInst *ir_implicit_cast2(IrAnalyze *ira, Scope *scope, AstNode *source_node,
221 Stage1AirInst *value, ZigType *expected_type);
222static Stage1AirInst *ir_get_deref(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *ptr,
223 ResultLoc *result_loc);
224static Stage1AirInst *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
225 Scope *scope, AstNode *source_node, Stage1AirInst *container_ptr, AstNode *container_ptr_src,
226 ZigType *container_type, bool initializing);
227static Stage1AirInst *ir_get_var_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigVar *var);
228static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, Stage1AirInst *op);
229static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
230static ZigType *adjust_ptr_const(CodeGen *g, ZigType *ptr_type, bool is_const);
231static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
232static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ZigValue *val);
233static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val);
234static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
235 ZigValue *out_val, ZigValue *ptr_val);
236static Stage1AirInst *ir_analyze_ptr_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node,
237 Stage1AirInst *ptr, AstNode *ptr_src, ZigType *dest_type, AstNode *dest_type_src,
238 bool safety_check_on, bool keep_bigger_alignment);
239static ZigValue *ir_resolve_const(IrAnalyze *ira, Stage1AirInst *value, UndefAllowed undef_allowed);
240static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
241static Stage1AirInst *ir_analyze_int_to_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *target,
242 ZigType *ptr_type);
243static Stage1AirInst *ir_analyze_bit_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value,
244 ZigType *dest_type);
245static Stage1AirInst *ir_resolve_result_raw(IrAnalyze *ira, Stage1ZirInst *suspend_source_instr,
246 ResultLoc *result_loc, ZigType *value_type, Stage1AirInst *value, bool force_runtime, bool allow_discard);
247static Stage1AirInst *ir_resolve_result(IrAnalyze *ira, Stage1ZirInst *suspend_source_instr,
248 ResultLoc *result_loc, ZigType *value_type, Stage1AirInst *value, bool force_runtime, bool allow_discard);
249static Stage1AirInst *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, Scope *scope, AstNode *source_node,
250 Stage1AirInst *base_ptr, bool safety_check_on, bool initializing);
251static Stage1AirInst *ir_analyze_unwrap_error_payload(IrAnalyze *ira, Scope *scope, AstNode *source_node,
252 Stage1AirInst *base_ptr, bool safety_check_on, bool initializing);
253static Stage1AirInst *ir_analyze_unwrap_err_code(IrAnalyze *ira, Scope *scope, AstNode *source_node,
254 Stage1AirInst *base_ptr, bool initializing);
255static Stage1AirInst *ir_analyze_store_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node,
256 Stage1AirInst *ptr, Stage1AirInst *uncasted_value, bool allow_write_through_const);
257static void ir_reset_result(ResultLoc *result_loc);
258static Stage1AirInst *ir_analyze_struct_field_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node,
259 TypeStructField *field, Stage1AirInst *struct_ptr, ZigType *struct_type, bool initializing);
260static Stage1AirInst *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name,
261 Scope *scope, AstNode *source_node, Stage1AirInst *container_ptr, ZigType *container_type);
262static Stage1AirInst *ir_analyze_test_non_null(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value);
263static Stage1AirInst *ir_error_dependency_loop(IrAnalyze *ira, AstNode *source_node);
264static Stage1AirInst *ir_const_undef(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *ty);
265static Stage1AirInst *ir_analyze_union_init(IrAnalyze *ira, Scope *scope, AstNode *source_node,
266 AstNode *field_source_node, ZigType *union_type, Buf *field_name, Stage1AirInst *field_result_loc,
267 Stage1AirInst *result_loc);
268static Stage1AirInst *ir_analyze_struct_value_field_value(IrAnalyze *ira, Scope *scope, AstNode *source_node,
269 Stage1AirInst *struct_operand, TypeStructField *field);
270static bool value_cmp_numeric_val_any(ZigValue *left, Cmp predicate, ZigValue *right);
271static bool value_cmp_numeric_val_all(ZigValue *left, Cmp predicate, ZigValue *right);
272static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, TypeStructField *field);
273static void value_to_bigfloat(BigFloat *out, ZigValue *val);
274
275static Error ir_resolve_lazy_recurse(AstNode *source_node, ZigValue *val);
276static Error ir_resolve_lazy_recurse_array(AstNode *source_node, ZigValue *val, size_t len);
277
278
279static void ir_assert_impl(bool ok, Stage1AirInst *source_instruction, char const *file, unsigned int line) {
280 if (ok) return;
281 src_assert_impl(ok, source_instruction->source_node, file, line);
282}
283
284#define ir_assert(OK, SOURCE_INSTRUCTION) ir_assert_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__)
285
286void destroy_instruction_gen(Stage1AirInst *inst) {
287 switch (inst->id) {
288 case Stage1AirInstIdInvalid:
289 zig_unreachable();
290 case Stage1AirInstIdReturn:
291 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstReturn *>(inst));
292 case Stage1AirInstIdConst:
293 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstConst *>(inst));
294 case Stage1AirInstIdBinOp:
295 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstBinOp *>(inst));
296 case Stage1AirInstIdCast:
297 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstCast *>(inst));
298 case Stage1AirInstIdCall:
299 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstCall *>(inst));
300 case Stage1AirInstIdCondBr:
301 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstCondBr *>(inst));
302 case Stage1AirInstIdBr:
303 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstBr *>(inst));
304 case Stage1AirInstIdPhi:
305 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstPhi *>(inst));
306 case Stage1AirInstIdUnreachable:
307 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstUnreachable *>(inst));
308 case Stage1AirInstIdElemPtr:
309 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstElemPtr *>(inst));
310 case Stage1AirInstIdVarPtr:
311 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstVarPtr *>(inst));
312 case Stage1AirInstIdReturnPtr:
313 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstReturnPtr *>(inst));
314 case Stage1AirInstIdLoadPtr:
315 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstLoadPtr *>(inst));
316 case Stage1AirInstIdStorePtr:
317 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstStorePtr *>(inst));
318 case Stage1AirInstIdVectorStoreElem:
319 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstVectorStoreElem *>(inst));
320 case Stage1AirInstIdStructFieldPtr:
321 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstStructFieldPtr *>(inst));
322 case Stage1AirInstIdUnionFieldPtr:
323 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstUnionFieldPtr *>(inst));
324 case Stage1AirInstIdAsm:
325 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstAsm *>(inst));
326 case Stage1AirInstIdTestNonNull:
327 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstTestNonNull *>(inst));
328 case Stage1AirInstIdOptionalUnwrapPtr:
329 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstOptionalUnwrapPtr *>(inst));
330 case Stage1AirInstIdPopCount:
331 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstPopCount *>(inst));
332 case Stage1AirInstIdClz:
333 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstClz *>(inst));
334 case Stage1AirInstIdCtz:
335 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstCtz *>(inst));
336 case Stage1AirInstIdBswap:
337 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstBswap *>(inst));
338 case Stage1AirInstIdBitReverse:
339 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstBitReverse *>(inst));
340 case Stage1AirInstIdSwitchBr:
341 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstSwitchBr *>(inst));
342 case Stage1AirInstIdUnionTag:
343 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstUnionTag *>(inst));
344 case Stage1AirInstIdRef:
345 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstRef *>(inst));
346 case Stage1AirInstIdErrName:
347 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstErrName *>(inst));
348 case Stage1AirInstIdCmpxchg:
349 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstCmpxchg *>(inst));
350 case Stage1AirInstIdFence:
351 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstFence *>(inst));
352 case Stage1AirInstIdReduce:
353 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstReduce *>(inst));
354 case Stage1AirInstIdTruncate:
355 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstTruncate *>(inst));
356 case Stage1AirInstIdShuffleVector:
357 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstShuffleVector *>(inst));
358 case Stage1AirInstIdSelect:
359 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstSelect *>(inst));
360 case Stage1AirInstIdSplat:
361 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstSplat *>(inst));
362 case Stage1AirInstIdBoolNot:
363 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstBoolNot *>(inst));
364 case Stage1AirInstIdMemset:
365 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstMemset *>(inst));
366 case Stage1AirInstIdMemcpy:
367 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstMemcpy *>(inst));
368 case Stage1AirInstIdSlice:
369 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstSlice *>(inst));
370 case Stage1AirInstIdBreakpoint:
371 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstBreakpoint *>(inst));
372 case Stage1AirInstIdReturnAddress:
373 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstReturnAddress *>(inst));
374 case Stage1AirInstIdFrameAddress:
375 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstFrameAddress *>(inst));
376 case Stage1AirInstIdFrameHandle:
377 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstFrameHandle *>(inst));
378 case Stage1AirInstIdFrameSize:
379 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstFrameSize *>(inst));
380 case Stage1AirInstIdOverflowOp:
381 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstOverflowOp *>(inst));
382 case Stage1AirInstIdTestErr:
383 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstTestErr *>(inst));
384 case Stage1AirInstIdUnwrapErrCode:
385 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstUnwrapErrCode *>(inst));
386 case Stage1AirInstIdUnwrapErrPayload:
387 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstUnwrapErrPayload *>(inst));
388 case Stage1AirInstIdOptionalWrap:
389 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstOptionalWrap *>(inst));
390 case Stage1AirInstIdErrWrapCode:
391 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstErrWrapCode *>(inst));
392 case Stage1AirInstIdErrWrapPayload:
393 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstErrWrapPayload *>(inst));
394 case Stage1AirInstIdPtrCast:
395 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstPtrCast *>(inst));
396 case Stage1AirInstIdBitCast:
397 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstBitCast *>(inst));
398 case Stage1AirInstIdWidenOrShorten:
399 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstWidenOrShorten *>(inst));
400 case Stage1AirInstIdPtrToInt:
401 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstPtrToInt *>(inst));
402 case Stage1AirInstIdIntToPtr:
403 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstIntToPtr *>(inst));
404 case Stage1AirInstIdIntToEnum:
405 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstIntToEnum *>(inst));
406 case Stage1AirInstIdIntToErr:
407 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstIntToErr *>(inst));
408 case Stage1AirInstIdErrToInt:
409 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstErrToInt *>(inst));
410 case Stage1AirInstIdTagName:
411 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstTagName *>(inst));
412 case Stage1AirInstIdPanic:
413 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstPanic *>(inst));
414 case Stage1AirInstIdFieldParentPtr:
415 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstFieldParentPtr *>(inst));
416 case Stage1AirInstIdAlignCast:
417 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstAlignCast *>(inst));
418 case Stage1AirInstIdErrorReturnTrace:
419 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstErrorReturnTrace *>(inst));
420 case Stage1AirInstIdAtomicRmw:
421 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstAtomicRmw *>(inst));
422 case Stage1AirInstIdSaveErrRetAddr:
423 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstSaveErrRetAddr *>(inst));
424 case Stage1AirInstIdFloatOp:
425 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstFloatOp *>(inst));
426 case Stage1AirInstIdMulAdd:
427 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstMulAdd *>(inst));
428 case Stage1AirInstIdAtomicLoad:
429 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstAtomicLoad *>(inst));
430 case Stage1AirInstIdAtomicStore:
431 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstAtomicStore *>(inst));
432 case Stage1AirInstIdDeclVar:
433 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstDeclVar *>(inst));
434 case Stage1AirInstIdArrayToVector:
435 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstArrayToVector *>(inst));
436 case Stage1AirInstIdVectorToArray:
437 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstVectorToArray *>(inst));
438 case Stage1AirInstIdPtrOfArrayToSlice:
439 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstPtrOfArrayToSlice *>(inst));
440 case Stage1AirInstIdAssertZero:
441 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstAssertZero *>(inst));
442 case Stage1AirInstIdAssertNonNull:
443 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstAssertNonNull *>(inst));
444 case Stage1AirInstIdAlloca:
445 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstAlloca *>(inst));
446 case Stage1AirInstIdSuspendBegin:
447 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstSuspendBegin *>(inst));
448 case Stage1AirInstIdSuspendFinish:
449 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstSuspendFinish *>(inst));
450 case Stage1AirInstIdResume:
451 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstResume *>(inst));
452 case Stage1AirInstIdAwait:
453 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstAwait *>(inst));
454 case Stage1AirInstIdSpillBegin:
455 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstSpillBegin *>(inst));
456 case Stage1AirInstIdSpillEnd:
457 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstSpillEnd *>(inst));
458 case Stage1AirInstIdVectorExtractElem:
459 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstVectorExtractElem *>(inst));
460 case Stage1AirInstIdBinaryNot:
461 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstBinaryNot *>(inst));
462 case Stage1AirInstIdNegation:
463 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstNegation *>(inst));
464 case Stage1AirInstIdWasmMemorySize:
465 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstWasmMemorySize *>(inst));
466 case Stage1AirInstIdWasmMemoryGrow:
467 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstWasmMemoryGrow *>(inst));
468 case Stage1AirInstIdExtern:
469 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstExtern *>(inst));
470 case Stage1AirInstIdPrefetch:
471 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstPrefetch *>(inst));
472 }
473 zig_unreachable();
474}
475
476static void ira_ref(IrAnalyze *ira) {
477 ira->ref_count += 1;
478}
479static void ira_deref(IrAnalyze *ira) {
480 if (ira->ref_count > 1) {
481 ira->ref_count -= 1;
482
483 // immediate destruction of dangling Stage1AirInstConst is not possible
484 // free tracking memory because it will never be used
485 ira->new_irb.constants.deinit(&heap::c_allocator);
486 return;
487 }
488 assert(ira->ref_count != 0);
489
490 for (size_t bb_i = 0; bb_i < ira->zir->basic_block_list.length; bb_i += 1) {
491 Stage1ZirBasicBlock *pass1_bb = ira->zir->basic_block_list.items[bb_i];
492 for (size_t inst_i = 0; inst_i < pass1_bb->instruction_list.length; inst_i += 1) {
493 Stage1ZirInst *pass1_inst = pass1_bb->instruction_list.items[inst_i];
494 destroy_instruction_src(pass1_inst);
495 }
496 heap::c_allocator.destroy(pass1_bb);
497 }
498 ira->zir->basic_block_list.deinit();
499 ira->zir->tld_list.deinit();
500 heap::c_allocator.destroy(ira->zir);
501 ira->src_implicit_return_type_list.deinit();
502 ira->resume_stack.deinit();
503
504 // destroy dangling Stage1AirInstConst
505 for (size_t i = 0; i < ira->new_irb.constants.length; i += 1) {
506 auto constant = ira->new_irb.constants.items[i];
507 if (constant->base.ref_count == 0 && !ir_inst_gen_has_side_effects(&constant->base))
508 destroy_instruction_gen(&constant->base);
509 }
510 ira->new_irb.constants.deinit(&heap::c_allocator);
511
512 heap::c_allocator.destroy(ira);
513}
514
515static ZigValue *const_ptr_pointee_unchecked_no_isf(CodeGen *g, ZigValue *const_val) {
516 assert(get_src_ptr_type(const_val->type) != nullptr);
517 assert(const_val->special == ConstValSpecialStatic);
518
519 switch (type_has_one_possible_value(g, const_val->type->data.pointer.child_type)) {
520 case OnePossibleValueInvalid:
521 return nullptr;
522 case OnePossibleValueYes:
523 return get_the_one_possible_value(g, const_val->type->data.pointer.child_type);
524 case OnePossibleValueNo:
525 break;
526 }
527
528 ZigValue *result;
529 switch (const_val->data.x_ptr.special) {
530 case ConstPtrSpecialInvalid:
531 zig_unreachable();
532 case ConstPtrSpecialRef:
533 result = const_val->data.x_ptr.data.ref.pointee;
534 break;
535 case ConstPtrSpecialBaseArray: {
536 ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
537 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
538 if (elem_index == array_val->type->data.array.len) {
539 result = array_val->type->data.array.sentinel;
540 } else {
541 expand_undef_array(g, array_val);
542 result = &array_val->data.x_array.data.s_none.elements[elem_index];
543 }
544 break;
545 }
546 case ConstPtrSpecialSubArray: {
547 ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
548 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
549
550 expand_undef_array(g, array_val);
551 result = g->pass1_arena->create<ZigValue>();
552 result->special = array_val->special;
553 result->type = get_array_type(g, array_val->type->data.array.child_type,
554 array_val->type->data.array.len - elem_index, array_val->type->data.array.sentinel);
555 result->data.x_array.special = ConstArraySpecialNone;
556 result->data.x_array.data.s_none.elements = &array_val->data.x_array.data.s_none.elements[elem_index];
557 result->parent.id = ConstParentIdArray;
558 result->parent.data.p_array.array_val = array_val;
559 result->parent.data.p_array.elem_index = elem_index;
560 break;
561 }
562 case ConstPtrSpecialBaseStruct: {
563 ZigValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val;
564 expand_undef_struct(g, struct_val);
565 size_t field_index = const_val->data.x_ptr.data.base_struct.field_index;
566 assert(struct_val->type->id == ZigTypeIdStruct);
567 assert(!struct_val->type->data.structure.fields[field_index]->is_comptime);
568 result = struct_val->data.x_struct.fields[field_index];
569 break;
570 }
571 case ConstPtrSpecialBaseErrorUnionCode:
572 result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set;
573 break;
574 case ConstPtrSpecialBaseErrorUnionPayload:
575 result = const_val->data.x_ptr.data.base_err_union_payload.err_union_val->data.x_err_union.payload;
576 break;
577 case ConstPtrSpecialBaseOptionalPayload:
578 result = const_val->data.x_ptr.data.base_optional_payload.optional_val->data.x_optional;
579 break;
580 case ConstPtrSpecialNull:
581 result = const_val;
582 break;
583 case ConstPtrSpecialHardCodedAddr:
584 zig_unreachable();
585 case ConstPtrSpecialDiscard:
586 zig_unreachable();
587 case ConstPtrSpecialFunction:
588 zig_unreachable();
589 }
590 assert(result != nullptr);
591 return result;
592}
593
594static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {
595 assert(get_src_ptr_type(const_val->type) != nullptr);
596 assert(const_val->special == ConstValSpecialStatic);
597
598 InferredStructField *isf = const_val->type->data.pointer.inferred_struct_field;
599 if (isf != nullptr) {
600 TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
601 assert(field != nullptr);
602 if (field->is_comptime) {
603 assert(field->init_val != nullptr);
604 return field->init_val;
605 }
606 ZigValue *struct_val = const_ptr_pointee_unchecked_no_isf(g, const_val);
607 assert(struct_val->type->id == ZigTypeIdStruct);
608 return struct_val->data.x_struct.fields[field->src_index];
609 }
610
611 return const_ptr_pointee_unchecked_no_isf(g, const_val);
612}
613
614static bool is_tuple(ZigType *type) {
615 return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialInferredTuple;
616}
617
618static bool is_slice(ZigType *type) {
619 return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialSlice;
620}
621
622// This function returns true when you can change the type of a ZigValue and the
623// value remains meaningful.
624static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expected, ZigType *actual) {
625 if (expected == actual)
626 return true;
627
628 if (get_src_ptr_type(expected) != nullptr && get_src_ptr_type(actual) != nullptr)
629 return true;
630
631 if (is_opt_err_set(expected) && is_opt_err_set(actual))
632 return true;
633
634 // XXX: Vectors and arrays are interchangeable at comptime
635 if (expected->id != actual->id)
636 return false;
637
638 switch (expected->id) {
639 case ZigTypeIdInvalid:
640 case ZigTypeIdUnreachable:
641 zig_unreachable();
642 case ZigTypeIdMetaType:
643 case ZigTypeIdVoid:
644 case ZigTypeIdBool:
645 case ZigTypeIdComptimeFloat:
646 case ZigTypeIdComptimeInt:
647 case ZigTypeIdEnumLiteral:
648 case ZigTypeIdUndefined:
649 case ZigTypeIdNull:
650 case ZigTypeIdBoundFn:
651 case ZigTypeIdErrorSet:
652 case ZigTypeIdOpaque:
653 case ZigTypeIdAnyFrame:
654 case ZigTypeIdFn:
655 return true;
656 case ZigTypeIdPointer:
657 return expected->data.pointer.inferred_struct_field == actual->data.pointer.inferred_struct_field;
658 case ZigTypeIdFloat:
659 return expected->data.floating.bit_count == actual->data.floating.bit_count;
660 case ZigTypeIdInt:
661 return expected->data.integral.is_signed == actual->data.integral.is_signed;
662 case ZigTypeIdStruct:
663 return is_slice(expected) && is_slice(actual);
664 case ZigTypeIdOptional:
665 case ZigTypeIdErrorUnion:
666 case ZigTypeIdEnum:
667 case ZigTypeIdUnion:
668 case ZigTypeIdFnFrame:
669 return false;
670 case ZigTypeIdVector:
671 return expected->data.vector.len == actual->data.vector.len &&
672 types_have_same_zig_comptime_repr(codegen, expected->data.vector.elem_type, actual->data.vector.elem_type);
673 case ZigTypeIdArray:
674 return expected->data.array.len == actual->data.array.len &&
675 expected->data.array.child_type == actual->data.array.child_type &&
676 (expected->data.array.sentinel == nullptr || (actual->data.array.sentinel != nullptr &&
677 const_values_equal(codegen, expected->data.array.sentinel, actual->data.array.sentinel)));
678 }
679 zig_unreachable();
680}
681
682static void ir_inst_gen_append(Stage1AirBasicBlock *basic_block, Stage1AirInst *instruction) {
683 assert(basic_block);
684 assert(instruction);
685 basic_block->instruction_list.append(instruction);
686}
687
688static size_t exec_next_debug_id_gen(Stage1Air *exec) {
689 size_t result = exec->next_debug_id;
690 exec->next_debug_id += 1;
691 return result;
692}
693
694static bool value_is_comptime(ZigValue *const_val) {
695 return const_val->special != ConstValSpecialRuntime;
696}
697
698static bool instr_is_comptime(Stage1AirInst *instruction) {
699 return value_is_comptime(instruction->value);
700}
701
702static void ir_ref_inst_gen(Stage1AirInst *instruction) {
703 assert(instruction->id != Stage1AirInstIdInvalid);
704 instruction->ref_count += 1;
705}
706
707static void create_result_ptr(CodeGen *codegen, ZigType *expected_type,
708 ZigValue **out_result, ZigValue **out_result_ptr)
709{
710 ZigValue *result = codegen->pass1_arena->create<ZigValue>();
711 ZigValue *result_ptr = codegen->pass1_arena->create<ZigValue>();
712 result->special = ConstValSpecialUndef;
713 result->type = expected_type;
714 result_ptr->special = ConstValSpecialStatic;
715 result_ptr->type = get_pointer_to_type(codegen, result->type, false);
716 result_ptr->data.x_ptr.mut = ConstPtrMutComptimeVar;
717 result_ptr->data.x_ptr.special = ConstPtrSpecialRef;
718 result_ptr->data.x_ptr.data.ref.pointee = result;
719
720 *out_result = result;
721 *out_result_ptr = result_ptr;
722}
723
724ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) {
725 Error err;
726
727 ZigValue *result;
728 ZigValue *result_ptr;
729 create_result_ptr(ira->codegen, ira->codegen->builtin_types.entry_type, &result, &result_ptr);
730
731 if ((err = ir_eval_const_value(ira->codegen, scope, node, result_ptr,
732 ira->backward_branch_count, ira->backward_branch_quota,
733 nullptr, nullptr, node, nullptr, ira->new_irb.exec, nullptr, UndefBad)))
734 {
735 return ira->codegen->builtin_types.entry_invalid;
736 }
737 if (type_is_invalid(result->type))
738 return ira->codegen->builtin_types.entry_invalid;
739
740 assert(result->special != ConstValSpecialRuntime);
741 ZigType *res_type = result->data.x_type;
742
743 return res_type;
744}
745
746static Stage1AirBasicBlock *ir_create_basic_block_gen(IrAnalyze *ira, Scope *scope, const char *name_hint) {
747 Stage1AirBasicBlock *result = heap::c_allocator.create<Stage1AirBasicBlock>();
748 result->scope = scope;
749 result->name_hint = name_hint;
750 result->debug_id = exec_next_debug_id_gen(ira->new_irb.exec);
751 return result;
752}
753
754static Stage1AirBasicBlock *ir_build_bb_from(IrAnalyze *ira, Stage1ZirBasicBlock *other_bb) {
755 Stage1AirBasicBlock *new_bb = ir_create_basic_block_gen(ira, other_bb->scope, other_bb->name_hint);
756 other_bb->child = new_bb;
757 return new_bb;
758}
759
760static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstDeclVar *) {
761 return Stage1AirInstIdDeclVar;
762}
763
764static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBr *) {
765 return Stage1AirInstIdBr;
766}
767
768static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstCondBr *) {
769 return Stage1AirInstIdCondBr;
770}
771
772static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSwitchBr *) {
773 return Stage1AirInstIdSwitchBr;
774}
775
776static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPhi *) {
777 return Stage1AirInstIdPhi;
778}
779
780static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBinaryNot *) {
781 return Stage1AirInstIdBinaryNot;
782}
783
784static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstNegation *) {
785 return Stage1AirInstIdNegation;
786}
787
788static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBinOp *) {
789 return Stage1AirInstIdBinOp;
790}
791
792static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstLoadPtr *) {
793 return Stage1AirInstIdLoadPtr;
794}
795
796static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstStorePtr *) {
797 return Stage1AirInstIdStorePtr;
798}
799
800static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstVectorStoreElem *) {
801 return Stage1AirInstIdVectorStoreElem;
802}
803
804static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstStructFieldPtr *) {
805 return Stage1AirInstIdStructFieldPtr;
806}
807
808static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstUnionFieldPtr *) {
809 return Stage1AirInstIdUnionFieldPtr;
810}
811
812static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstElemPtr *) {
813 return Stage1AirInstIdElemPtr;
814}
815
816static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstVarPtr *) {
817 return Stage1AirInstIdVarPtr;
818}
819
820static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstReturnPtr *) {
821 return Stage1AirInstIdReturnPtr;
822}
823
824static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstCall *) {
825 return Stage1AirInstIdCall;
826}
827
828static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstReturn *) {
829 return Stage1AirInstIdReturn;
830}
831
832static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstCast *) {
833 return Stage1AirInstIdCast;
834}
835
836static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstUnreachable *) {
837 return Stage1AirInstIdUnreachable;
838}
839
840static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAsm *) {
841 return Stage1AirInstIdAsm;
842}
843
844static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstTestNonNull *) {
845 return Stage1AirInstIdTestNonNull;
846}
847
848static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstOptionalUnwrapPtr *) {
849 return Stage1AirInstIdOptionalUnwrapPtr;
850}
851
852static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstOptionalWrap *) {
853 return Stage1AirInstIdOptionalWrap;
854}
855
856static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstUnionTag *) {
857 return Stage1AirInstIdUnionTag;
858}
859
860static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstClz *) {
861 return Stage1AirInstIdClz;
862}
863
864static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstCtz *) {
865 return Stage1AirInstIdCtz;
866}
867
868static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPopCount *) {
869 return Stage1AirInstIdPopCount;
870}
871
872static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBswap *) {
873 return Stage1AirInstIdBswap;
874}
875
876static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBitReverse *) {
877 return Stage1AirInstIdBitReverse;
878}
879
880static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstRef *) {
881 return Stage1AirInstIdRef;
882}
883
884static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstErrName *) {
885 return Stage1AirInstIdErrName;
886}
887
888static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstCmpxchg *) {
889 return Stage1AirInstIdCmpxchg;
890}
891
892static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstFence *) {
893 return Stage1AirInstIdFence;
894}
895
896static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstReduce *) {
897 return Stage1AirInstIdReduce;
898}
899
900static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstTruncate *) {
901 return Stage1AirInstIdTruncate;
902}
903
904static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstShuffleVector *) {
905 return Stage1AirInstIdShuffleVector;
906}
907
908static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSelect *) {
909 return Stage1AirInstIdSelect;
910}
911
912static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSplat *) {
913 return Stage1AirInstIdSplat;
914}
915
916static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBoolNot *) {
917 return Stage1AirInstIdBoolNot;
918}
919
920static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstMemset *) {
921 return Stage1AirInstIdMemset;
922}
923
924static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstMemcpy *) {
925 return Stage1AirInstIdMemcpy;
926}
927
928static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSlice *) {
929 return Stage1AirInstIdSlice;
930}
931
932static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBreakpoint *) {
933 return Stage1AirInstIdBreakpoint;
934}
935
936static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstReturnAddress *) {
937 return Stage1AirInstIdReturnAddress;
938}
939
940static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstFrameAddress *) {
941 return Stage1AirInstIdFrameAddress;
942}
943
944static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstFrameHandle *) {
945 return Stage1AirInstIdFrameHandle;
946}
947
948static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstFrameSize *) {
949 return Stage1AirInstIdFrameSize;
950}
951
952static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstOverflowOp *) {
953 return Stage1AirInstIdOverflowOp;
954}
955
956static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstTestErr *) {
957 return Stage1AirInstIdTestErr;
958}
959
960static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstMulAdd *) {
961 return Stage1AirInstIdMulAdd;
962}
963
964static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstFloatOp *) {
965 return Stage1AirInstIdFloatOp;
966}
967
968static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstUnwrapErrCode *) {
969 return Stage1AirInstIdUnwrapErrCode;
970}
971
972static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstUnwrapErrPayload *) {
973 return Stage1AirInstIdUnwrapErrPayload;
974}
975
976static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstErrWrapCode *) {
977 return Stage1AirInstIdErrWrapCode;
978}
979
980static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstErrWrapPayload *) {
981 return Stage1AirInstIdErrWrapPayload;
982}
983
984static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPtrCast *) {
985 return Stage1AirInstIdPtrCast;
986}
987
988static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBitCast *) {
989 return Stage1AirInstIdBitCast;
990}
991
992static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstWidenOrShorten *) {
993 return Stage1AirInstIdWidenOrShorten;
994}
995
996static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstIntToPtr *) {
997 return Stage1AirInstIdIntToPtr;
998}
999
1000static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPtrToInt *) {
1001 return Stage1AirInstIdPtrToInt;
1002}
1003
1004static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstIntToEnum *) {
1005 return Stage1AirInstIdIntToEnum;
1006}
1007
1008static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstIntToErr *) {
1009 return Stage1AirInstIdIntToErr;
1010}
1011
1012static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstErrToInt *) {
1013 return Stage1AirInstIdErrToInt;
1014}
1015
1016static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPanic *) {
1017 return Stage1AirInstIdPanic;
1018}
1019
1020static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstTagName *) {
1021 return Stage1AirInstIdTagName;
1022}
1023
1024static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstFieldParentPtr *) {
1025 return Stage1AirInstIdFieldParentPtr;
1026}
1027
1028static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAlignCast *) {
1029 return Stage1AirInstIdAlignCast;
1030}
1031
1032static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstErrorReturnTrace *) {
1033 return Stage1AirInstIdErrorReturnTrace;
1034}
1035
1036static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAtomicRmw *) {
1037 return Stage1AirInstIdAtomicRmw;
1038}
1039
1040static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAtomicLoad *) {
1041 return Stage1AirInstIdAtomicLoad;
1042}
1043
1044static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAtomicStore *) {
1045 return Stage1AirInstIdAtomicStore;
1046}
1047
1048static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSaveErrRetAddr *) {
1049 return Stage1AirInstIdSaveErrRetAddr;
1050}
1051
1052static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstVectorToArray *) {
1053 return Stage1AirInstIdVectorToArray;
1054}
1055
1056static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstArrayToVector *) {
1057 return Stage1AirInstIdArrayToVector;
1058}
1059
1060static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAssertZero *) {
1061 return Stage1AirInstIdAssertZero;
1062}
1063
1064static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAssertNonNull *) {
1065 return Stage1AirInstIdAssertNonNull;
1066}
1067
1068static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPtrOfArrayToSlice *) {
1069 return Stage1AirInstIdPtrOfArrayToSlice;
1070}
1071
1072static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSuspendBegin *) {
1073 return Stage1AirInstIdSuspendBegin;
1074}
1075
1076static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSuspendFinish *) {
1077 return Stage1AirInstIdSuspendFinish;
1078}
1079
1080static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAwait *) {
1081 return Stage1AirInstIdAwait;
1082}
1083
1084static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstResume *) {
1085 return Stage1AirInstIdResume;
1086}
1087
1088static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSpillBegin *) {
1089 return Stage1AirInstIdSpillBegin;
1090}
1091
1092static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSpillEnd *) {
1093 return Stage1AirInstIdSpillEnd;
1094}
1095
1096static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstVectorExtractElem *) {
1097 return Stage1AirInstIdVectorExtractElem;
1098}
1099
1100static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAlloca *) {
1101 return Stage1AirInstIdAlloca;
1102}
1103
1104static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstConst *) {
1105 return Stage1AirInstIdConst;
1106}
1107
1108static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstWasmMemorySize *) {
1109 return Stage1AirInstIdWasmMemorySize;
1110}
1111
1112static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstWasmMemoryGrow *) {
1113 return Stage1AirInstIdWasmMemoryGrow;
1114}
1115
1116static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstExtern *) {
1117 return Stage1AirInstIdExtern;
1118}
1119
1120static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPrefetch *) {
1121 return Stage1AirInstIdPrefetch;
1122}
1123
1124template<typename T>
1125static T *ir_create_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) {
1126 T *special_instruction = heap::c_allocator.create<T>();
1127 special_instruction->base.id = ir_inst_id(special_instruction);
1128 special_instruction->base.scope = scope;
1129 special_instruction->base.source_node = source_node;
1130 special_instruction->base.debug_id = exec_next_debug_id_gen(irb->exec);
1131 special_instruction->base.value = irb->codegen->pass1_arena->create<ZigValue>();
1132 return special_instruction;
1133}
1134
1135template<typename T>
1136static T *ir_create_inst_noval(IrBuilderGen *irb, Scope *scope, AstNode *source_node) {
1137 T *special_instruction = heap::c_allocator.create<T>();
1138 special_instruction->base.id = ir_inst_id(special_instruction);
1139 special_instruction->base.scope = scope;
1140 special_instruction->base.source_node = source_node;
1141 special_instruction->base.debug_id = exec_next_debug_id_gen(irb->exec);
1142 return special_instruction;
1143}
1144
1145template<typename T>
1146static T *ir_build_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) {
1147 T *special_instruction = ir_create_inst_gen<T>(irb, scope, source_node);
1148 ir_inst_gen_append(irb->current_basic_block, &special_instruction->base);
1149 return special_instruction;
1150}
1151
1152template<typename T>
1153static T *ir_build_inst_noreturn(IrBuilderGen *irb, Scope *scope, AstNode *source_node) {
1154 T *special_instruction = ir_create_inst_noval<T>(irb, scope, source_node);
1155 special_instruction->base.value = irb->codegen->intern.for_unreachable();
1156 ir_inst_gen_append(irb->current_basic_block, &special_instruction->base);
1157 return special_instruction;
1158}
1159
1160template<typename T>
1161static T *ir_build_inst_void(IrBuilderGen *irb, Scope *scope, AstNode *source_node) {
1162 T *special_instruction = ir_create_inst_noval<T>(irb, scope, source_node);
1163 special_instruction->base.value = irb->codegen->intern.for_void();
1164 ir_inst_gen_append(irb->current_basic_block, &special_instruction->base);
1165 return special_instruction;
1166}
1167
1168Stage1AirInst *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn,
1169 ZigType *var_type, const char *name_hint)
1170{
1171 Stage1AirInstAlloca *alloca_gen = heap::c_allocator.create<Stage1AirInstAlloca>();
1172 alloca_gen->base.id = Stage1AirInstIdAlloca;
1173 alloca_gen->base.source_node = source_node;
1174 alloca_gen->base.scope = scope;
1175 alloca_gen->base.value = g->pass1_arena->create<ZigValue>();
1176 alloca_gen->base.value->type = get_pointer_to_type(g, var_type, false);
1177 alloca_gen->base.ref_count = 1;
1178 alloca_gen->name_hint = name_hint;
1179 fn->alloca_gen_list.append(alloca_gen);
1180 return &alloca_gen->base;
1181}
1182
1183static Stage1AirInst *ir_build_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1184 ZigType *dest_type, Stage1AirInst *value, CastOp cast_op)
1185{
1186 Stage1AirInstCast *inst = ir_build_inst_gen<Stage1AirInstCast>(&ira->new_irb, scope, source_node);
1187 inst->base.value->type = dest_type;
1188 inst->value = value;
1189 inst->cast_op = cast_op;
1190
1191 ir_ref_inst_gen(value);
1192
1193 return &inst->base;
1194}
1195
1196static Stage1AirInst *ir_build_cond_br_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *condition,
1197 Stage1AirBasicBlock *then_block, Stage1AirBasicBlock *else_block)
1198{
1199 Stage1AirInstCondBr *inst = ir_build_inst_noreturn<Stage1AirInstCondBr>(&ira->new_irb, scope, source_node);
1200 inst->condition = condition;
1201 inst->then_block = then_block;
1202 inst->else_block = else_block;
1203
1204 ir_ref_inst_gen(condition);
1205
1206 return &inst->base;
1207}
1208
1209static Stage1AirInst *ir_build_return_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *operand) {
1210 Stage1AirInstReturn *inst = ir_build_inst_noreturn<Stage1AirInstReturn>(&ira->new_irb, scope, source_node);
1211 inst->operand = operand;
1212
1213 if (operand != nullptr) ir_ref_inst_gen(operand);
1214
1215 return &inst->base;
1216}
1217
1218static Stage1AirInst *ir_build_bin_op_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *res_type,
1219 IrBinOp op_id, Stage1AirInst *op1, Stage1AirInst *op2, bool safety_check_on)
1220{
1221 Stage1AirInstBinOp *inst = ir_build_inst_gen<Stage1AirInstBinOp>(&ira->new_irb,
1222 scope, source_node);
1223 inst->base.value->type = res_type;
1224 inst->op_id = op_id;
1225 inst->op1 = op1;
1226 inst->op2 = op2;
1227 inst->safety_check_on = safety_check_on;
1228
1229 ir_ref_inst_gen(op1);
1230 ir_ref_inst_gen(op2);
1231
1232 return &inst->base;
1233}
1234
1235
1236static Stage1AirInst *ir_build_var_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigVar *var) {
1237 Stage1AirInstVarPtr *instruction = ir_build_inst_gen<Stage1AirInstVarPtr>(&ira->new_irb, scope, source_node);
1238 instruction->var = var;
1239
1240 var->ref_count += 1;
1241
1242 return &instruction->base;
1243}
1244
1245static Stage1AirInst *ir_build_return_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *ty) {
1246 Stage1AirInstReturnPtr *instruction = ir_build_inst_gen<Stage1AirInstReturnPtr>(&ira->new_irb, scope, source_node);
1247 instruction->base.value->type = ty;
1248 return &instruction->base;
1249}
1250
1251static Stage1AirInst *ir_build_elem_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1252 Stage1AirInst *array_ptr, Stage1AirInst *elem_index, bool safety_check_on, ZigType *return_type)
1253{
1254 Stage1AirInstElemPtr *instruction = ir_build_inst_gen<Stage1AirInstElemPtr>(&ira->new_irb, scope, source_node);
1255 instruction->base.value->type = return_type;
1256 instruction->array_ptr = array_ptr;
1257 instruction->elem_index = elem_index;
1258 instruction->safety_check_on = safety_check_on;
1259
1260 ir_ref_inst_gen(array_ptr);
1261 ir_ref_inst_gen(elem_index);
1262
1263 return &instruction->base;
1264}
1265
1266static Stage1AirInst *ir_build_struct_field_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1267 Stage1AirInst *struct_ptr, TypeStructField *field, ZigType *ptr_type)
1268{
1269 Stage1AirInstStructFieldPtr *inst = ir_build_inst_gen<Stage1AirInstStructFieldPtr>(&ira->new_irb, scope, source_node);
1270 inst->base.value->type = ptr_type;
1271 inst->struct_ptr = struct_ptr;
1272 inst->field = field;
1273
1274 ir_ref_inst_gen(struct_ptr);
1275
1276 return &inst->base;
1277}
1278
1279static Stage1AirInst *ir_build_union_field_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1280 Stage1AirInst *union_ptr, TypeUnionField *field, bool safety_check_on, bool initializing, ZigType *ptr_type)
1281{
1282 Stage1AirInstUnionFieldPtr *inst = ir_build_inst_gen<Stage1AirInstUnionFieldPtr>(&ira->new_irb,
1283 scope, source_node);
1284 inst->base.value->type = ptr_type;
1285 inst->initializing = initializing;
1286 inst->safety_check_on = safety_check_on;
1287 inst->union_ptr = union_ptr;
1288 inst->field = field;
1289
1290 ir_ref_inst_gen(union_ptr);
1291
1292 return &inst->base;
1293}
1294
1295static Stage1AirInstCall *ir_build_call_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1296 ZigFn *fn_entry, Stage1AirInst *fn_ref, size_t arg_count, Stage1AirInst **args,
1297 CallModifier modifier, Stage1AirInst *new_stack, bool is_async_call_builtin,
1298 Stage1AirInst *result_loc, ZigType *return_type)
1299{
1300 Stage1AirInstCall *call_instruction = ir_build_inst_gen<Stage1AirInstCall>(&ira->new_irb,
1301 scope, source_node);
1302 call_instruction->base.value->type = return_type;
1303 call_instruction->fn_entry = fn_entry;
1304 call_instruction->fn_ref = fn_ref;
1305 call_instruction->args = args;
1306 call_instruction->arg_count = arg_count;
1307 call_instruction->modifier = modifier;
1308 call_instruction->is_async_call_builtin = is_async_call_builtin;
1309 call_instruction->new_stack = new_stack;
1310 call_instruction->result_loc = result_loc;
1311
1312 if (fn_ref != nullptr) ir_ref_inst_gen(fn_ref);
1313 for (size_t i = 0; i < arg_count; i += 1)
1314 ir_ref_inst_gen(args[i]);
1315 if (new_stack != nullptr) ir_ref_inst_gen(new_stack);
1316 if (result_loc != nullptr) ir_ref_inst_gen(result_loc);
1317
1318 return call_instruction;
1319}
1320
1321static Stage1AirInst *ir_build_phi_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, bool merge_comptime,
1322 size_t incoming_count, Stage1AirBasicBlock **incoming_blocks, Stage1AirInst **incoming_values, ZigType *result_type)
1323{
1324 assert(incoming_count != 0);
1325 assert(incoming_count != SIZE_MAX);
1326
1327 if (merge_comptime && instr_is_comptime(incoming_values[incoming_count - 1])) {
1328 // We need to check whether all the merged values are comptime-known and equal.
1329 // If so, we elide the runtime phi and replace it with any of the identical comptime-known values.
1330 ZigValue *comptime_value = ir_resolve_const(ira, incoming_values[incoming_count - 1], UndefOk);
1331 if (comptime_value == nullptr)
1332 return ira->codegen->invalid_inst_gen;
1333
1334 for (size_t i = incoming_count - 1; i > 0;) {
1335 i -= 1;
1336 if (!instr_is_comptime(incoming_values[i])) {
1337 comptime_value = nullptr;
1338 break;
1339 }
1340 ZigValue *value = ir_resolve_const(ira, incoming_values[i], UndefOk);
1341 if (value == nullptr)
1342 return ira->codegen->invalid_inst_gen;
1343 if (!const_values_equal(ira->codegen, comptime_value, value)) {
1344 comptime_value = nullptr;
1345 break;
1346 }
1347 }
1348 if (comptime_value != nullptr)
1349 return incoming_values[0];
1350 }
1351
1352 Stage1AirInstPhi *phi_instruction = ir_build_inst_gen<Stage1AirInstPhi>(&ira->new_irb,
1353 scope, source_node);
1354 phi_instruction->base.value->type = result_type;
1355 phi_instruction->incoming_count = incoming_count;
1356 phi_instruction->incoming_blocks = incoming_blocks;
1357 phi_instruction->incoming_values = incoming_values;
1358
1359 for (size_t i = 0; i < incoming_count; i += 1) {
1360 ir_ref_inst_gen(incoming_values[i]);
1361 }
1362
1363 return &phi_instruction->base;
1364}
1365
1366static Stage1AirInst *ir_build_br_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirBasicBlock *dest_block) {
1367 Stage1AirInstBr *inst = ir_build_inst_noreturn<Stage1AirInstBr>(&ira->new_irb, scope, source_node);
1368 inst->dest_block = dest_block;
1369
1370 return &inst->base;
1371}
1372
1373static Stage1AirInst *ir_build_negation(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *operand, ZigType *expr_type, bool wrapping) {
1374 Stage1AirInstNegation *instruction = ir_build_inst_gen<Stage1AirInstNegation>(&ira->new_irb,
1375 scope, source_node);
1376 instruction->base.value->type = expr_type;
1377 instruction->operand = operand;
1378 instruction->wrapping = wrapping;
1379
1380 ir_ref_inst_gen(operand);
1381
1382 return &instruction->base;
1383}
1384
1385static Stage1AirInst *ir_build_binary_not(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *operand,
1386 ZigType *expr_type)
1387{
1388 Stage1AirInstBinaryNot *instruction = ir_build_inst_gen<Stage1AirInstBinaryNot>(&ira->new_irb,
1389 scope, source_node);
1390 instruction->base.value->type = expr_type;
1391 instruction->operand = operand;
1392
1393 ir_ref_inst_gen(operand);
1394
1395 return &instruction->base;
1396}
1397
1398static Stage1AirInst *ir_build_unreachable_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node) {
1399 Stage1AirInstUnreachable *inst = ir_build_inst_noreturn<Stage1AirInstUnreachable>(&ira->new_irb, scope, source_node);
1400 return &inst->base;
1401}
1402
1403static Stage1AirInst *ir_build_store_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *ptr, Stage1AirInst *value) {
1404 Stage1AirInstStorePtr *instruction = ir_build_inst_void<Stage1AirInstStorePtr>(&ira->new_irb,
1405 scope, source_node);
1406 instruction->ptr = ptr;
1407 instruction->value = value;
1408
1409 ir_ref_inst_gen(ptr);
1410 ir_ref_inst_gen(value);
1411
1412 return &instruction->base;
1413}
1414
1415static Stage1AirInst *ir_build_vector_store_elem(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1416 Stage1AirInst *vector_ptr, Stage1AirInst *index, Stage1AirInst *value)
1417{
1418 Stage1AirInstVectorStoreElem *inst = ir_build_inst_void<Stage1AirInstVectorStoreElem>(
1419 &ira->new_irb, scope, source_node);
1420 inst->vector_ptr = vector_ptr;
1421 inst->index = index;
1422 inst->value = value;
1423
1424 ir_ref_inst_gen(vector_ptr);
1425 ir_ref_inst_gen(index);
1426 ir_ref_inst_gen(value);
1427
1428 return &inst->base;
1429}
1430
1431static Stage1AirInst *ir_build_var_decl_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1432 ZigVar *var, Stage1AirInst *var_ptr)
1433{
1434 Stage1AirInstDeclVar *inst = ir_build_inst_gen<Stage1AirInstDeclVar>(&ira->new_irb,
1435 scope, source_node);
1436 inst->base.value->special = ConstValSpecialStatic;
1437 inst->base.value->type = ira->codegen->builtin_types.entry_void;
1438 inst->var = var;
1439 inst->var_ptr = var_ptr;
1440
1441 ir_ref_inst_gen(var_ptr);
1442
1443 return &inst->base;
1444}
1445
1446static Stage1AirInst *ir_build_extern_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Buf *name,
1447 GlobalLinkageId linkage, bool is_thread_local, ZigType *expr_type)
1448{
1449 Stage1AirInstExtern *instruction = ir_build_inst_gen<Stage1AirInstExtern>(&ira->new_irb,
1450 scope, source_node);
1451 instruction->base.value->type = expr_type;
1452 instruction->name = name;
1453 instruction->linkage = linkage;
1454 instruction->is_thread_local = is_thread_local;
1455
1456 return &instruction->base;
1457}
1458
1459static Stage1AirInst *ir_build_load_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1460 Stage1AirInst *ptr, ZigType *ty, Stage1AirInst *result_loc)
1461{
1462 Stage1AirInstLoadPtr *instruction = ir_build_inst_gen<Stage1AirInstLoadPtr>(
1463 &ira->new_irb, scope, source_node);
1464 instruction->base.value->type = ty;
1465 instruction->ptr = ptr;
1466 instruction->result_loc = result_loc;
1467
1468 ir_ref_inst_gen(ptr);
1469 if (result_loc != nullptr) ir_ref_inst_gen(result_loc);
1470
1471 return &instruction->base;
1472}
1473
1474static Stage1AirInst *ir_build_asm_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1475 Buf *asm_template, AsmToken *token_list, size_t token_list_len,
1476 Stage1AirInst **input_list, Stage1AirInst **output_types, ZigVar **output_vars, size_t return_count,
1477 bool has_side_effects, ZigType *return_type)
1478{
1479 Stage1AirInstAsm *instruction = ir_build_inst_gen<Stage1AirInstAsm>(&ira->new_irb, scope, source_node);
1480 instruction->base.value->type = return_type;
1481 instruction->asm_template = asm_template;
1482 instruction->token_list = token_list;
1483 instruction->token_list_len = token_list_len;
1484 instruction->input_list = input_list;
1485 instruction->output_types = output_types;
1486 instruction->output_vars = output_vars;
1487 instruction->return_count = return_count;
1488 instruction->has_side_effects = has_side_effects;
1489
1490 assert(source_node->type == NodeTypeAsmExpr);
1491 for (size_t i = 0; i < source_node->data.asm_expr.output_list.length; i += 1) {
1492 Stage1AirInst *output_type = output_types[i];
1493 if (output_type) ir_ref_inst_gen(output_type);
1494 }
1495
1496 for (size_t i = 0; i < source_node->data.asm_expr.input_list.length; i += 1) {
1497 Stage1AirInst *input_value = input_list[i];
1498 ir_ref_inst_gen(input_value);
1499 }
1500
1501 return &instruction->base;
1502}
1503
1504static Stage1AirInst *ir_build_test_non_null_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value) {
1505 Stage1AirInstTestNonNull *inst = ir_build_inst_gen<Stage1AirInstTestNonNull>(&ira->new_irb,
1506 scope, source_node);
1507 inst->base.value->type = ira->codegen->builtin_types.entry_bool;
1508 inst->value = value;
1509
1510 ir_ref_inst_gen(value);
1511
1512 return &inst->base;
1513}
1514
1515static Stage1AirInst *ir_build_optional_unwrap_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1516 Stage1AirInst *base_ptr, bool safety_check_on, bool initializing, ZigType *result_type)
1517{
1518 Stage1AirInstOptionalUnwrapPtr *inst = ir_build_inst_gen<Stage1AirInstOptionalUnwrapPtr>(&ira->new_irb,
1519 scope, source_node);
1520 inst->base.value->type = result_type;
1521 inst->base_ptr = base_ptr;
1522 inst->safety_check_on = safety_check_on;
1523 inst->initializing = initializing;
1524
1525 ir_ref_inst_gen(base_ptr);
1526
1527 return &inst->base;
1528}
1529
1530static Stage1AirInst *ir_build_optional_wrap(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *result_ty,
1531 Stage1AirInst *operand, Stage1AirInst *result_loc)
1532{
1533 Stage1AirInstOptionalWrap *instruction = ir_build_inst_gen<Stage1AirInstOptionalWrap>(
1534 &ira->new_irb, scope, source_node);
1535 instruction->base.value->type = result_ty;
1536 instruction->operand = operand;
1537 instruction->result_loc = result_loc;
1538
1539 ir_ref_inst_gen(operand);
1540 if (result_loc != nullptr) ir_ref_inst_gen(result_loc);
1541
1542 return &instruction->base;
1543}
1544
1545static Stage1AirInst *ir_build_err_wrap_payload(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1546 ZigType *result_type, Stage1AirInst *operand, Stage1AirInst *result_loc)
1547{
1548 Stage1AirInstErrWrapPayload *instruction = ir_build_inst_gen<Stage1AirInstErrWrapPayload>(
1549 &ira->new_irb, scope, source_node);
1550 instruction->base.value->type = result_type;
1551 instruction->operand = operand;
1552 instruction->result_loc = result_loc;
1553
1554 ir_ref_inst_gen(operand);
1555 if (result_loc != nullptr) ir_ref_inst_gen(result_loc);
1556
1557 return &instruction->base;
1558}
1559
1560static Stage1AirInst *ir_build_err_wrap_code(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1561 ZigType *result_type, Stage1AirInst *operand, Stage1AirInst *result_loc)
1562{
1563 Stage1AirInstErrWrapCode *instruction = ir_build_inst_gen<Stage1AirInstErrWrapCode>(
1564 &ira->new_irb, scope, source_node);
1565 instruction->base.value->type = result_type;
1566 instruction->operand = operand;
1567 instruction->result_loc = result_loc;
1568
1569 ir_ref_inst_gen(operand);
1570 if (result_loc != nullptr) ir_ref_inst_gen(result_loc);
1571
1572 return &instruction->base;
1573}
1574
1575static Stage1AirInst *ir_build_clz_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *result_type, Stage1AirInst *op) {
1576 Stage1AirInstClz *instruction = ir_build_inst_gen<Stage1AirInstClz>(&ira->new_irb,
1577 scope, source_node);
1578 instruction->base.value->type = result_type;
1579 instruction->op = op;
1580
1581 ir_ref_inst_gen(op);
1582
1583 return &instruction->base;
1584}
1585
1586static Stage1AirInst *ir_build_ctz_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *result_type, Stage1AirInst *op) {
1587 Stage1AirInstCtz *instruction = ir_build_inst_gen<Stage1AirInstCtz>(&ira->new_irb,
1588 scope, source_node);
1589 instruction->base.value->type = result_type;
1590 instruction->op = op;
1591
1592 ir_ref_inst_gen(op);
1593
1594 return &instruction->base;
1595}
1596
1597static Stage1AirInst *ir_build_pop_count_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *result_type,
1598 Stage1AirInst *op)
1599{
1600 Stage1AirInstPopCount *instruction = ir_build_inst_gen<Stage1AirInstPopCount>(&ira->new_irb,
1601 scope, source_node);
1602 instruction->base.value->type = result_type;
1603 instruction->op = op;
1604
1605 ir_ref_inst_gen(op);
1606
1607 return &instruction->base;
1608}
1609
1610static Stage1AirInst *ir_build_bswap_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *op_type,
1611 Stage1AirInst *op)
1612{
1613 Stage1AirInstBswap *instruction = ir_build_inst_gen<Stage1AirInstBswap>(&ira->new_irb,
1614 scope, source_node);
1615 instruction->base.value->type = op_type;
1616 instruction->op = op;
1617
1618 ir_ref_inst_gen(op);
1619
1620 return &instruction->base;
1621}
1622
1623static Stage1AirInst *ir_build_bit_reverse_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *int_type,
1624 Stage1AirInst *op)
1625{
1626 Stage1AirInstBitReverse *instruction = ir_build_inst_gen<Stage1AirInstBitReverse>(&ira->new_irb,
1627 scope, source_node);
1628 instruction->base.value->type = int_type;
1629 instruction->op = op;
1630
1631 ir_ref_inst_gen(op);
1632
1633 return &instruction->base;
1634}
1635
1636static Stage1AirInstSwitchBr *ir_build_switch_br_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1637 Stage1AirInst *target_value, Stage1AirBasicBlock *else_block, size_t case_count, Stage1AirInstSwitchBrCase *cases)
1638{
1639 Stage1AirInstSwitchBr *instruction = ir_build_inst_noreturn<Stage1AirInstSwitchBr>(&ira->new_irb,
1640 scope, source_node);
1641 instruction->target_value = target_value;
1642 instruction->else_block = else_block;
1643 instruction->case_count = case_count;
1644 instruction->cases = cases;
1645
1646 ir_ref_inst_gen(target_value);
1647
1648 for (size_t i = 0; i < case_count; i += 1) {
1649 ir_ref_inst_gen(cases[i].value);
1650 }
1651
1652 return instruction;
1653}
1654
1655static Stage1AirInst *ir_build_union_tag(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value,
1656 ZigType *tag_type)
1657{
1658 Stage1AirInstUnionTag *instruction = ir_build_inst_gen<Stage1AirInstUnionTag>(&ira->new_irb,
1659 scope, source_node);
1660 instruction->value = value;
1661 instruction->base.value->type = tag_type;
1662
1663 ir_ref_inst_gen(value);
1664
1665 return &instruction->base;
1666}
1667
1668static Stage1AirInst *ir_build_ref_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *result_type,
1669 Stage1AirInst *operand, Stage1AirInst *result_loc)
1670{
1671 Stage1AirInstRef *instruction = ir_build_inst_gen<Stage1AirInstRef>(&ira->new_irb,
1672 scope, source_node);
1673 instruction->base.value->type = result_type;
1674 instruction->operand = operand;
1675 instruction->result_loc = result_loc;
1676
1677 ir_ref_inst_gen(operand);
1678 if (result_loc != nullptr) ir_ref_inst_gen(result_loc);
1679
1680 return &instruction->base;
1681}
1682
1683static Stage1AirInst *ir_build_err_name_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value,
1684 ZigType *str_type)
1685{
1686 Stage1AirInstErrName *instruction = ir_build_inst_gen<Stage1AirInstErrName>(&ira->new_irb,
1687 scope, source_node);
1688 instruction->base.value->type = str_type;
1689 instruction->value = value;
1690
1691 ir_ref_inst_gen(value);
1692
1693 return &instruction->base;
1694}
1695
1696static Stage1AirInst *ir_build_cmpxchg_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *result_type,
1697 Stage1AirInst *ptr, Stage1AirInst *cmp_value, Stage1AirInst *new_value,
1698 AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, Stage1AirInst *result_loc)
1699{
1700 Stage1AirInstCmpxchg *instruction = ir_build_inst_gen<Stage1AirInstCmpxchg>(&ira->new_irb,
1701 scope, source_node);
1702 instruction->base.value->type = result_type;
1703 instruction->ptr = ptr;
1704 instruction->cmp_value = cmp_value;
1705 instruction->new_value = new_value;
1706 instruction->success_order = success_order;
1707 instruction->failure_order = failure_order;
1708 instruction->is_weak = is_weak;
1709 instruction->result_loc = result_loc;
1710
1711 ir_ref_inst_gen(ptr);
1712 ir_ref_inst_gen(cmp_value);
1713 ir_ref_inst_gen(new_value);
1714 if (result_loc != nullptr) ir_ref_inst_gen(result_loc);
1715
1716 return &instruction->base;
1717}
1718
1719static Stage1AirInst *ir_build_fence_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, AtomicOrder order) {
1720 Stage1AirInstFence *instruction = ir_build_inst_void<Stage1AirInstFence>(&ira->new_irb,
1721 scope, source_node);
1722 instruction->order = order;
1723
1724 return &instruction->base;
1725}
1726
1727static Stage1AirInst *ir_build_reduce_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ReduceOp op, Stage1AirInst *value, ZigType *result_type) {
1728 Stage1AirInstReduce *instruction = ir_build_inst_gen<Stage1AirInstReduce>(&ira->new_irb,
1729 scope, source_node);
1730 instruction->base.value->type = result_type;
1731 instruction->op = op;
1732 instruction->value = value;
1733
1734 ir_ref_inst_gen(value);
1735
1736 return &instruction->base;
1737}
1738
1739static void ir_set_cursor_at_end_gen(IrBuilderGen *irb, Stage1AirBasicBlock *basic_block) {
1740 assert(basic_block);
1741 irb->current_basic_block = basic_block;
1742}
1743
1744static void ir_append_basic_block_gen(IrBuilderGen *irb, Stage1AirBasicBlock *bb) {
1745 assert(!bb->already_appended);
1746 bb->already_appended = true;
1747 irb->exec->basic_block_list.append(bb);
1748}
1749
1750static void ir_set_cursor_at_end_and_append_block_gen(IrBuilderGen *irb, Stage1AirBasicBlock *basic_block) {
1751 ir_append_basic_block_gen(irb, basic_block);
1752 ir_set_cursor_at_end_gen(irb, basic_block);
1753}
1754
1755static Stage1AirInst *ir_build_suspend_begin_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node) {
1756 Stage1AirInstSuspendBegin *inst = ir_build_inst_void<Stage1AirInstSuspendBegin>(&ira->new_irb,
1757 scope, source_node);
1758 return &inst->base;
1759}
1760
1761static Stage1AirInst *ir_build_save_err_ret_addr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node) {
1762 Stage1AirInstSaveErrRetAddr *inst = ir_build_inst_void<Stage1AirInstSaveErrRetAddr>(&ira->new_irb,
1763 scope, source_node);
1764 return &inst->base;
1765}
1766
1767static Stage1AirInst *ir_build_truncate_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *dest_type,
1768 Stage1AirInst *target)
1769{
1770 Stage1AirInstTruncate *instruction = ir_build_inst_gen<Stage1AirInstTruncate>(&ira->new_irb,
1771 scope, source_node);
1772 instruction->base.value->type = dest_type;
1773 instruction->target = target;
1774
1775 ir_ref_inst_gen(target);
1776
1777 return &instruction->base;
1778}
1779
1780static Stage1AirInst *ir_build_shuffle_vector_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1781 ZigType *result_type, Stage1AirInst *a, Stage1AirInst *b, Stage1AirInst *mask)
1782{
1783 Stage1AirInstShuffleVector *inst = ir_build_inst_gen<Stage1AirInstShuffleVector>(&ira->new_irb, scope, source_node);
1784 inst->base.value->type = result_type;
1785 inst->a = a;
1786 inst->b = b;
1787 inst->mask = mask;
1788
1789 ir_ref_inst_gen(a);
1790 ir_ref_inst_gen(b);
1791 ir_ref_inst_gen(mask);
1792
1793 return &inst->base;
1794}
1795
1796static Stage1AirInst *ir_build_select_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1797 ZigType *result_type, Stage1AirInst *pred, Stage1AirInst *a, Stage1AirInst *b)
1798{
1799 Stage1AirInstSelect *inst = ir_build_inst_gen<Stage1AirInstSelect>(&ira->new_irb, scope, source_node);
1800 inst->base.value->type = result_type;
1801 inst->pred = pred;
1802 inst->a = a;
1803 inst->b = b;
1804
1805 ir_ref_inst_gen(pred);
1806 ir_ref_inst_gen(a);
1807 ir_ref_inst_gen(b);
1808
1809 return &inst->base;
1810}
1811
1812static Stage1AirInst *ir_build_splat_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *result_type,
1813 Stage1AirInst *scalar)
1814{
1815 Stage1AirInstSplat *instruction = ir_build_inst_gen<Stage1AirInstSplat>(
1816 &ira->new_irb, scope, source_node);
1817 instruction->base.value->type = result_type;
1818 instruction->scalar = scalar;
1819
1820 ir_ref_inst_gen(scalar);
1821
1822 return &instruction->base;
1823}
1824
1825static Stage1AirInst *ir_build_bool_not_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value) {
1826 Stage1AirInstBoolNot *instruction = ir_build_inst_gen<Stage1AirInstBoolNot>(&ira->new_irb,
1827 scope, source_node);
1828 instruction->base.value->type = ira->codegen->builtin_types.entry_bool;
1829 instruction->value = value;
1830
1831 ir_ref_inst_gen(value);
1832
1833 return &instruction->base;
1834}
1835
1836static Stage1AirInst *ir_build_memset_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1837 Stage1AirInst *dest_ptr, Stage1AirInst *byte, Stage1AirInst *count)
1838{
1839 Stage1AirInstMemset *instruction = ir_build_inst_void<Stage1AirInstMemset>(&ira->new_irb,
1840 scope, source_node);
1841 instruction->dest_ptr = dest_ptr;
1842 instruction->byte = byte;
1843 instruction->count = count;
1844
1845 ir_ref_inst_gen(dest_ptr);
1846 ir_ref_inst_gen(byte);
1847 ir_ref_inst_gen(count);
1848
1849 return &instruction->base;
1850}
1851
1852static Stage1AirInst *ir_build_memcpy_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1853 Stage1AirInst *dest_ptr, Stage1AirInst *src_ptr, Stage1AirInst *count)
1854{
1855 Stage1AirInstMemcpy *instruction = ir_build_inst_void<Stage1AirInstMemcpy>(&ira->new_irb,
1856 scope, source_node);
1857 instruction->dest_ptr = dest_ptr;
1858 instruction->src_ptr = src_ptr;
1859 instruction->count = count;
1860
1861 ir_ref_inst_gen(dest_ptr);
1862 ir_ref_inst_gen(src_ptr);
1863 ir_ref_inst_gen(count);
1864
1865 return &instruction->base;
1866}
1867
1868static Stage1AirInst *ir_build_slice_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *slice_type,
1869 Stage1AirInst *ptr, Stage1AirInst *start, Stage1AirInst *end, bool safety_check_on, Stage1AirInst *result_loc,
1870 ZigValue *sentinel)
1871{
1872 Stage1AirInstSlice *instruction = ir_build_inst_gen<Stage1AirInstSlice>(
1873 &ira->new_irb, scope, source_node);
1874 instruction->base.value->type = slice_type;
1875 instruction->ptr = ptr;
1876 instruction->start = start;
1877 instruction->end = end;
1878 instruction->safety_check_on = safety_check_on;
1879 instruction->result_loc = result_loc;
1880 instruction->sentinel = sentinel;
1881
1882 ir_ref_inst_gen(ptr);
1883 ir_ref_inst_gen(start);
1884 if (end != nullptr) ir_ref_inst_gen(end);
1885 if (result_loc != nullptr) ir_ref_inst_gen(result_loc);
1886
1887 return &instruction->base;
1888}
1889
1890static Stage1AirInst *ir_build_breakpoint_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node) {
1891 Stage1AirInstBreakpoint *instruction = ir_build_inst_void<Stage1AirInstBreakpoint>(&ira->new_irb,
1892 scope, source_node);
1893 return &instruction->base;
1894}
1895
1896static Stage1AirInst *ir_build_return_address_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node) {
1897 Stage1AirInstReturnAddress *inst = ir_build_inst_gen<Stage1AirInstReturnAddress>(&ira->new_irb, scope, source_node);
1898 inst->base.value->type = ira->codegen->builtin_types.entry_usize;
1899 return &inst->base;
1900}
1901
1902static Stage1AirInst *ir_build_frame_address_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node) {
1903 Stage1AirInstFrameAddress *inst = ir_build_inst_gen<Stage1AirInstFrameAddress>(&ira->new_irb, scope, source_node);
1904 inst->base.value->type = ira->codegen->builtin_types.entry_usize;
1905 return &inst->base;
1906}
1907
1908static Stage1AirInst *ir_build_handle_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *ty) {
1909 Stage1AirInstFrameHandle *inst = ir_build_inst_gen<Stage1AirInstFrameHandle>(&ira->new_irb, scope, source_node);
1910 inst->base.value->type = ty;
1911 return &inst->base;
1912}
1913
1914static Stage1AirInst *ir_build_frame_size_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *fn)
1915{
1916 Stage1AirInstFrameSize *inst = ir_build_inst_gen<Stage1AirInstFrameSize>(&ira->new_irb, scope, source_node);
1917 inst->base.value->type = ira->codegen->builtin_types.entry_usize;
1918 inst->fn = fn;
1919
1920 ir_ref_inst_gen(fn);
1921
1922 return &inst->base;
1923}
1924
1925static Stage1AirInst *ir_build_overflow_op_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1926 IrOverflowOp op, Stage1AirInst *op1, Stage1AirInst *op2, Stage1AirInst *result_ptr,
1927 ZigType *result_ptr_type)
1928{
1929 Stage1AirInstOverflowOp *instruction = ir_build_inst_gen<Stage1AirInstOverflowOp>(&ira->new_irb,
1930 scope, source_node);
1931 instruction->base.value->type = ira->codegen->builtin_types.entry_bool;
1932 instruction->op = op;
1933 instruction->op1 = op1;
1934 instruction->op2 = op2;
1935 instruction->result_ptr = result_ptr;
1936 instruction->result_ptr_type = result_ptr_type;
1937
1938 ir_ref_inst_gen(op1);
1939 ir_ref_inst_gen(op2);
1940 ir_ref_inst_gen(result_ptr);
1941
1942 return &instruction->base;
1943}
1944
1945static Stage1AirInst *ir_build_float_op_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *operand,
1946 BuiltinFnId fn_id, ZigType *operand_type)
1947{
1948 Stage1AirInstFloatOp *instruction = ir_build_inst_gen<Stage1AirInstFloatOp>(&ira->new_irb,
1949 scope, source_node);
1950 instruction->base.value->type = operand_type;
1951 instruction->operand = operand;
1952 instruction->fn_id = fn_id;
1953
1954 ir_ref_inst_gen(operand);
1955
1956 return &instruction->base;
1957}
1958
1959static Stage1AirInst *ir_build_mul_add_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *op1, Stage1AirInst *op2,
1960 Stage1AirInst *op3, ZigType *expr_type)
1961{
1962 Stage1AirInstMulAdd *instruction = ir_build_inst_gen<Stage1AirInstMulAdd>(&ira->new_irb,
1963 scope, source_node);
1964 instruction->base.value->type = expr_type;
1965 instruction->op1 = op1;
1966 instruction->op2 = op2;
1967 instruction->op3 = op3;
1968
1969 ir_ref_inst_gen(op1);
1970 ir_ref_inst_gen(op2);
1971 ir_ref_inst_gen(op3);
1972
1973 return &instruction->base;
1974}
1975
1976static Stage1AirInst *ir_build_test_err_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *err_union) {
1977 Stage1AirInstTestErr *instruction = ir_build_inst_gen<Stage1AirInstTestErr>(
1978 &ira->new_irb, scope, source_node);
1979 instruction->base.value->type = ira->codegen->builtin_types.entry_bool;
1980 instruction->err_union = err_union;
1981
1982 ir_ref_inst_gen(err_union);
1983
1984 return &instruction->base;
1985}
1986
1987static Stage1AirInst *ir_build_unwrap_err_code_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1988 Stage1AirInst *err_union_ptr, ZigType *result_type)
1989{
1990 Stage1AirInstUnwrapErrCode *inst = ir_build_inst_gen<Stage1AirInstUnwrapErrCode>(&ira->new_irb, scope, source_node);
1991 inst->base.value->type = result_type;
1992 inst->err_union_ptr = err_union_ptr;
1993
1994 ir_ref_inst_gen(err_union_ptr);
1995
1996 return &inst->base;
1997}
1998
1999static Stage1AirInst *ir_build_unwrap_err_payload_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2000 Stage1AirInst *value, bool safety_check_on, bool initializing, ZigType *result_type)
2001{
2002 Stage1AirInstUnwrapErrPayload *inst = ir_build_inst_gen<Stage1AirInstUnwrapErrPayload>(&ira->new_irb, scope, source_node);
2003 inst->base.value->type = result_type;
2004 inst->value = value;
2005 inst->safety_check_on = safety_check_on;
2006 inst->initializing = initializing;
2007
2008 ir_ref_inst_gen(value);
2009
2010 return &inst->base;
2011}
2012
2013static Stage1AirInst *ir_build_ptr_cast_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2014 ZigType *ptr_type, Stage1AirInst *ptr, bool safety_check_on)
2015{
2016 Stage1AirInstPtrCast *instruction = ir_build_inst_gen<Stage1AirInstPtrCast>(
2017 &ira->new_irb, scope, source_node);
2018 instruction->base.value->type = ptr_type;
2019 instruction->ptr = ptr;
2020 instruction->safety_check_on = safety_check_on;
2021
2022 ir_ref_inst_gen(ptr);
2023
2024 return &instruction->base;
2025}
2026
2027static Stage1AirInst *ir_build_bit_cast_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2028 Stage1AirInst *operand, ZigType *ty)
2029{
2030 Stage1AirInstBitCast *instruction = ir_build_inst_gen<Stage1AirInstBitCast>(
2031 &ira->new_irb, scope, source_node);
2032 instruction->base.value->type = ty;
2033 instruction->operand = operand;
2034
2035 ir_ref_inst_gen(operand);
2036
2037 return &instruction->base;
2038}
2039
2040static Stage1AirInst *ir_build_widen_or_shorten(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *target,
2041 ZigType *result_type)
2042{
2043 Stage1AirInstWidenOrShorten *inst = ir_build_inst_gen<Stage1AirInstWidenOrShorten>(&ira->new_irb, scope, source_node);
2044 inst->base.value->type = result_type;
2045 inst->target = target;
2046
2047 ir_ref_inst_gen(target);
2048
2049 return &inst->base;
2050}
2051
2052static Stage1AirInst *ir_build_int_to_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2053 Stage1AirInst *target, ZigType *ptr_type)
2054{
2055 Stage1AirInstIntToPtr *instruction = ir_build_inst_gen<Stage1AirInstIntToPtr>(&ira->new_irb, scope, source_node);
2056 instruction->base.value->type = ptr_type;
2057 instruction->target = target;
2058
2059 ir_ref_inst_gen(target);
2060
2061 return &instruction->base;
2062}
2063
2064static Stage1AirInst *ir_build_ptr_to_int_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *target) {
2065 Stage1AirInstPtrToInt *inst = ir_build_inst_gen<Stage1AirInstPtrToInt>(&ira->new_irb, scope, source_node);
2066 inst->base.value->type = ira->codegen->builtin_types.entry_usize;
2067 inst->target = target;
2068
2069 ir_ref_inst_gen(target);
2070
2071 return &inst->base;
2072}
2073
2074static Stage1AirInst *ir_build_int_to_enum_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2075 ZigType *dest_type, Stage1AirInst *target)
2076{
2077 Stage1AirInstIntToEnum *instruction = ir_build_inst_gen<Stage1AirInstIntToEnum>(&ira->new_irb, scope, source_node);
2078 instruction->base.value->type = dest_type;
2079 instruction->target = target;
2080
2081 ir_ref_inst_gen(target);
2082
2083 return &instruction->base;
2084}
2085
2086static Stage1AirInst *ir_build_int_to_err_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *target,
2087 ZigType *wanted_type)
2088{
2089 Stage1AirInstIntToErr *instruction = ir_build_inst_gen<Stage1AirInstIntToErr>(&ira->new_irb, scope, source_node);
2090 instruction->base.value->type = wanted_type;
2091 instruction->target = target;
2092
2093 ir_ref_inst_gen(target);
2094
2095 return &instruction->base;
2096}
2097
2098static Stage1AirInst *ir_build_err_to_int_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *target,
2099 ZigType *wanted_type)
2100{
2101 Stage1AirInstErrToInt *instruction = ir_build_inst_gen<Stage1AirInstErrToInt>(&ira->new_irb, scope, source_node);
2102 instruction->base.value->type = wanted_type;
2103 instruction->target = target;
2104
2105 ir_ref_inst_gen(target);
2106
2107 return &instruction->base;
2108}
2109
2110static Stage1AirInst *ir_build_panic_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *msg) {
2111 Stage1AirInstPanic *instruction = ir_build_inst_noreturn<Stage1AirInstPanic>(&ira->new_irb,
2112 scope, source_node);
2113 instruction->msg = msg;
2114
2115 ir_ref_inst_gen(msg);
2116
2117 return &instruction->base;
2118}
2119
2120static Stage1AirInst *ir_build_tag_name_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *target,
2121 ZigType *result_type)
2122{
2123 Stage1AirInstTagName *instruction = ir_build_inst_gen<Stage1AirInstTagName>(&ira->new_irb,
2124 scope, source_node);
2125 instruction->base.value->type = result_type;
2126 instruction->target = target;
2127
2128 ir_ref_inst_gen(target);
2129
2130 return &instruction->base;
2131}
2132
2133static Stage1AirInst *ir_build_field_parent_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2134 Stage1AirInst *field_ptr, TypeStructField *field, ZigType *result_type)
2135{
2136 Stage1AirInstFieldParentPtr *inst = ir_build_inst_gen<Stage1AirInstFieldParentPtr>(&ira->new_irb,
2137 scope, source_node);
2138 inst->base.value->type = result_type;
2139 inst->field_ptr = field_ptr;
2140 inst->field = field;
2141
2142 ir_ref_inst_gen(field_ptr);
2143
2144 return &inst->base;
2145}
2146
2147static Stage1AirInst *ir_build_align_cast_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *target,
2148 ZigType *result_type)
2149{
2150 Stage1AirInstAlignCast *instruction = ir_build_inst_gen<Stage1AirInstAlignCast>(&ira->new_irb, scope, source_node);
2151 instruction->base.value->type = result_type;
2152 instruction->target = target;
2153
2154 ir_ref_inst_gen(target);
2155
2156 return &instruction->base;
2157}
2158
2159static Stage1AirInst *ir_build_error_return_trace_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2160 IrInstErrorReturnTraceOptional optional, ZigType *result_type)
2161{
2162 Stage1AirInstErrorReturnTrace *inst = ir_build_inst_gen<Stage1AirInstErrorReturnTrace>(&ira->new_irb, scope, source_node);
2163 inst->base.value->type = result_type;
2164 inst->optional = optional;
2165
2166 return &inst->base;
2167}
2168
2169static Stage1AirInst *ir_build_atomic_rmw_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2170 Stage1AirInst *ptr, Stage1AirInst *operand, AtomicRmwOp op, AtomicOrder ordering, ZigType *operand_type)
2171{
2172 Stage1AirInstAtomicRmw *instruction = ir_build_inst_gen<Stage1AirInstAtomicRmw>(&ira->new_irb, scope, source_node);
2173 instruction->base.value->type = operand_type;
2174 instruction->ptr = ptr;
2175 instruction->op = op;
2176 instruction->operand = operand;
2177 instruction->ordering = ordering;
2178
2179 ir_ref_inst_gen(ptr);
2180 ir_ref_inst_gen(operand);
2181
2182 return &instruction->base;
2183}
2184
2185static Stage1AirInst *ir_build_atomic_load_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2186 Stage1AirInst *ptr, AtomicOrder ordering, ZigType *operand_type)
2187{
2188 Stage1AirInstAtomicLoad *instruction = ir_build_inst_gen<Stage1AirInstAtomicLoad>(&ira->new_irb,
2189 scope, source_node);
2190 instruction->base.value->type = operand_type;
2191 instruction->ptr = ptr;
2192 instruction->ordering = ordering;
2193
2194 ir_ref_inst_gen(ptr);
2195
2196 return &instruction->base;
2197}
2198
2199static Stage1AirInst *ir_build_atomic_store_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2200 Stage1AirInst *ptr, Stage1AirInst *value, AtomicOrder ordering)
2201{
2202 Stage1AirInstAtomicStore *instruction = ir_build_inst_void<Stage1AirInstAtomicStore>(&ira->new_irb,
2203 scope, source_node);
2204 instruction->ptr = ptr;
2205 instruction->value = value;
2206 instruction->ordering = ordering;
2207
2208 ir_ref_inst_gen(ptr);
2209 ir_ref_inst_gen(value);
2210
2211 return &instruction->base;
2212}
2213
2214
2215static Stage1AirInst *ir_build_vector_to_array(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2216 ZigType *result_type, Stage1AirInst *vector, Stage1AirInst *result_loc)
2217{
2218 Stage1AirInstVectorToArray *instruction = ir_build_inst_gen<Stage1AirInstVectorToArray>(&ira->new_irb,
2219 scope, source_node);
2220 instruction->base.value->type = result_type;
2221 instruction->vector = vector;
2222 instruction->result_loc = result_loc;
2223
2224 ir_ref_inst_gen(vector);
2225 ir_ref_inst_gen(result_loc);
2226
2227 return &instruction->base;
2228}
2229
2230static Stage1AirInst *ir_build_ptr_of_array_to_slice(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2231 ZigType *result_type, Stage1AirInst *operand, Stage1AirInst *result_loc)
2232{
2233 Stage1AirInstPtrOfArrayToSlice *instruction = ir_build_inst_gen<Stage1AirInstPtrOfArrayToSlice>(&ira->new_irb,
2234 scope, source_node);
2235 instruction->base.value->type = result_type;
2236 instruction->operand = operand;
2237 instruction->result_loc = result_loc;
2238
2239 ir_ref_inst_gen(operand);
2240 ir_ref_inst_gen(result_loc);
2241
2242 return &instruction->base;
2243}
2244
2245static Stage1AirInst *ir_build_array_to_vector(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2246 Stage1AirInst *array, ZigType *result_type)
2247{
2248 Stage1AirInstArrayToVector *instruction = ir_build_inst_gen<Stage1AirInstArrayToVector>(&ira->new_irb,
2249 scope, source_node);
2250 instruction->base.value->type = result_type;
2251 instruction->array = array;
2252
2253 ir_ref_inst_gen(array);
2254
2255 return &instruction->base;
2256}
2257
2258static Stage1AirInst *ir_build_assert_zero(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2259 Stage1AirInst *target)
2260{
2261 Stage1AirInstAssertZero *instruction = ir_build_inst_gen<Stage1AirInstAssertZero>(&ira->new_irb,
2262 scope, source_node);
2263 instruction->base.value->type = ira->codegen->builtin_types.entry_void;
2264 instruction->target = target;
2265
2266 ir_ref_inst_gen(target);
2267
2268 return &instruction->base;
2269}
2270
2271static Stage1AirInst *ir_build_assert_non_null(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2272 Stage1AirInst *target)
2273{
2274 Stage1AirInstAssertNonNull *instruction = ir_build_inst_gen<Stage1AirInstAssertNonNull>(&ira->new_irb,
2275 scope, source_node);
2276 instruction->base.value->type = ira->codegen->builtin_types.entry_void;
2277 instruction->target = target;
2278
2279 ir_ref_inst_gen(target);
2280
2281 return &instruction->base;
2282}
2283
2284static Stage1AirInstAlloca *ir_build_alloca_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2285 uint32_t align, const char *name_hint)
2286{
2287 Stage1AirInstAlloca *instruction = ir_create_inst_gen<Stage1AirInstAlloca>(&ira->new_irb,
2288 scope, source_node);
2289 instruction->align = align;
2290 instruction->name_hint = name_hint;
2291
2292 return instruction;
2293}
2294
2295static Stage1AirInst *ir_build_suspend_finish_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInstSuspendBegin *begin) {
2296 Stage1AirInstSuspendFinish *inst = ir_build_inst_void<Stage1AirInstSuspendFinish>(&ira->new_irb,
2297 scope, source_node);
2298 inst->begin = begin;
2299
2300 ir_ref_inst_gen(&begin->base);
2301
2302 return &inst->base;
2303}
2304
2305static Stage1AirInstAwait *ir_build_await_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2306 Stage1AirInst *frame, ZigType *result_type, Stage1AirInst *result_loc, bool is_nosuspend)
2307{
2308 Stage1AirInstAwait *instruction = ir_build_inst_gen<Stage1AirInstAwait>(&ira->new_irb,
2309 scope, source_node);
2310 instruction->base.value->type = result_type;
2311 instruction->frame = frame;
2312 instruction->result_loc = result_loc;
2313 instruction->is_nosuspend = is_nosuspend;
2314
2315 ir_ref_inst_gen(frame);
2316 if (result_loc != nullptr) ir_ref_inst_gen(result_loc);
2317
2318 return instruction;
2319}
2320
2321static Stage1AirInst *ir_build_resume_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *frame) {
2322 Stage1AirInstResume *instruction = ir_build_inst_void<Stage1AirInstResume>(&ira->new_irb,
2323 scope, source_node);
2324 instruction->frame = frame;
2325
2326 ir_ref_inst_gen(frame);
2327
2328 return &instruction->base;
2329}
2330
2331static Stage1AirInst *ir_build_spill_begin_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *operand,
2332 SpillId spill_id)
2333{
2334 Stage1AirInstSpillBegin *instruction = ir_build_inst_void<Stage1AirInstSpillBegin>(&ira->new_irb,
2335 scope, source_node);
2336 instruction->operand = operand;
2337 instruction->spill_id = spill_id;
2338
2339 ir_ref_inst_gen(operand);
2340
2341 return &instruction->base;
2342}
2343
2344static Stage1AirInst *ir_build_spill_end_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInstSpillBegin *begin,
2345 ZigType *result_type)
2346{
2347 Stage1AirInstSpillEnd *instruction = ir_build_inst_gen<Stage1AirInstSpillEnd>(&ira->new_irb,
2348 scope, source_node);
2349 instruction->base.value->type = result_type;
2350 instruction->begin = begin;
2351
2352 ir_ref_inst_gen(&begin->base);
2353
2354 return &instruction->base;
2355}
2356
2357static Stage1AirInst *ir_build_vector_extract_elem(IrAnalyze *ira, Scope *scope, AstNode *source_node,
2358 Stage1AirInst *vector, Stage1AirInst *index)
2359{
2360 Stage1AirInstVectorExtractElem *instruction = ir_build_inst_gen<Stage1AirInstVectorExtractElem>(
2361 &ira->new_irb, scope, source_node);
2362 instruction->base.value->type = vector->value->type->data.vector.elem_type;
2363 instruction->vector = vector;
2364 instruction->index = index;
2365
2366 ir_ref_inst_gen(vector);
2367 ir_ref_inst_gen(index);
2368
2369 return &instruction->base;
2370}
2371
2372static Stage1AirInst *ir_build_wasm_memory_size_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *index) {
2373 Stage1AirInstWasmMemorySize *instruction = ir_build_inst_gen<Stage1AirInstWasmMemorySize>(&ira->new_irb,
2374 scope, source_node);
2375 instruction->base.value->type = ira->codegen->builtin_types.entry_u32;
2376 instruction->index = index;
2377
2378 ir_ref_inst_gen(index);
2379
2380 return &instruction->base;
2381}
2382
2383static Stage1AirInst *ir_build_wasm_memory_grow_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *index, Stage1AirInst *delta) {
2384 Stage1AirInstWasmMemoryGrow *instruction = ir_build_inst_gen<Stage1AirInstWasmMemoryGrow>(&ira->new_irb,
2385 scope, source_node);
2386 instruction->base.value->type = ira->codegen->builtin_types.entry_i32;
2387 instruction->index = index;
2388 instruction->delta = delta;
2389
2390 ir_ref_inst_gen(index);
2391 ir_ref_inst_gen(delta);
2392
2393 return &instruction->base;
2394}
2395
2396static Error parse_asm_template(IrAnalyze *ira, AstNode *source_node, Buf *asm_template,
2397 ZigList<AsmToken> *tok_list)
2398{
2399 // TODO Connect the errors in this function back up to the actual source location
2400 // rather than just the token. https://github.com/ziglang/zig/issues/2080
2401 enum State {
2402 StateStart,
2403 StatePercent,
2404 StateTemplate,
2405 StateVar,
2406 };
2407
2408 assert(tok_list->length == 0);
2409
2410 AsmToken *cur_tok = nullptr;
2411
2412 enum State state = StateStart;
2413
2414 for (size_t i = 0; i < buf_len(asm_template); i += 1) {
2415 uint8_t c = *((uint8_t*)buf_ptr(asm_template) + i);
2416 switch (state) {
2417 case StateStart:
2418 if (c == '%') {
2419 tok_list->add_one();
2420 cur_tok = &tok_list->last();
2421 cur_tok->id = AsmTokenIdPercent;
2422 cur_tok->start = i;
2423 state = StatePercent;
2424 } else {
2425 tok_list->add_one();
2426 cur_tok = &tok_list->last();
2427 cur_tok->id = AsmTokenIdTemplate;
2428 cur_tok->start = i;
2429 state = StateTemplate;
2430 }
2431 break;
2432 case StatePercent:
2433 if (c == '%') {
2434 cur_tok->end = i;
2435 state = StateStart;
2436 } else if (c == '[') {
2437 cur_tok->id = AsmTokenIdVar;
2438 state = StateVar;
2439 } else if (c == '=') {
2440 cur_tok->id = AsmTokenIdUniqueId;
2441 cur_tok->end = i;
2442 state = StateStart;
2443 } else {
2444 add_node_error(ira->codegen, source_node,
2445 buf_create_from_str("expected a '%' or '['"));
2446 return ErrorSemanticAnalyzeFail;
2447 }
2448 break;
2449 case StateTemplate:
2450 if (c == '%') {
2451 cur_tok->end = i;
2452 i -= 1;
2453 cur_tok = nullptr;
2454 state = StateStart;
2455 }
2456 break;
2457 case StateVar:
2458 if (c == ']') {
2459 cur_tok->end = i;
2460 state = StateStart;
2461 } else if ((c >= 'a' && c <= 'z') ||
2462 (c >= '0' && c <= '9') ||
2463 (c == '_'))
2464 {
2465 // do nothing
2466 } else {
2467 add_node_error(ira->codegen, source_node,
2468 buf_sprintf("invalid substitution character: '%c'", c));
2469 return ErrorSemanticAnalyzeFail;
2470 }
2471 break;
2472 }
2473 }
2474
2475 switch (state) {
2476 case StateStart:
2477 break;
2478 case StatePercent:
2479 case StateVar:
2480 add_node_error(ira->codegen, source_node, buf_sprintf("unexpected end of assembly template"));
2481 return ErrorSemanticAnalyzeFail;
2482 case StateTemplate:
2483 cur_tok->end = buf_len(asm_template);
2484 break;
2485 }
2486 return ErrorNone;
2487}
2488
2489// errors should be populated with set1's values
2490static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigType *set1, ZigType *set2,
2491 Buf *type_name)
2492{
2493 assert(set1->id == ZigTypeIdErrorSet);
2494 assert(set2->id == ZigTypeIdErrorSet);
2495
2496 ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
2497 err_set_type->size_in_bits = g->builtin_types.entry_global_error_set->size_in_bits;
2498 err_set_type->abi_align = g->builtin_types.entry_global_error_set->abi_align;
2499 err_set_type->abi_size = g->builtin_types.entry_global_error_set->abi_size;
2500 if (type_name == nullptr) {
2501 buf_resize(&err_set_type->name, 0);
2502 buf_appendf(&err_set_type->name, "error{");
2503 } else {
2504 buf_init_from_buf(&err_set_type->name, type_name);
2505 }
2506
2507 for (uint32_t i = 0, count = set1->data.error_set.err_count; i < count; i += 1) {
2508 assert(errors[set1->data.error_set.errors[i]->value] == set1->data.error_set.errors[i]);
2509 }
2510
2511 uint32_t count = set1->data.error_set.err_count;
2512 for (uint32_t i = 0; i < set2->data.error_set.err_count; i += 1) {
2513 ErrorTableEntry *error_entry = set2->data.error_set.errors[i];
2514 if (errors[error_entry->value] == nullptr) {
2515 count += 1;
2516 }
2517 }
2518
2519 err_set_type->data.error_set.err_count = count;
2520 err_set_type->data.error_set.errors = heap::c_allocator.allocate<ErrorTableEntry *>(count);
2521
2522 bool need_comma = false;
2523 for (uint32_t i = 0; i < set1->data.error_set.err_count; i += 1) {
2524 ErrorTableEntry *error_entry = set1->data.error_set.errors[i];
2525 if (type_name == nullptr) {
2526 const char *comma = need_comma ? "," : "";
2527 need_comma = true;
2528 buf_appendf(&err_set_type->name, "%s%s", comma, buf_ptr(&error_entry->name));
2529 }
2530 err_set_type->data.error_set.errors[i] = error_entry;
2531 }
2532
2533 uint32_t index = set1->data.error_set.err_count;
2534 for (uint32_t i = 0; i < set2->data.error_set.err_count; i += 1) {
2535 ErrorTableEntry *error_entry = set2->data.error_set.errors[i];
2536 if (errors[error_entry->value] == nullptr) {
2537 errors[error_entry->value] = error_entry;
2538 if (type_name == nullptr) {
2539 const char *comma = need_comma ? "," : "";
2540 need_comma = true;
2541 buf_appendf(&err_set_type->name, "%s%s", comma, buf_ptr(&error_entry->name));
2542 }
2543 err_set_type->data.error_set.errors[index] = error_entry;
2544 index += 1;
2545 }
2546 }
2547 assert(index == count);
2548
2549 if (type_name == nullptr) {
2550 buf_appendf(&err_set_type->name, "}");
2551 }
2552
2553 return err_set_type;
2554
2555}
2556
2557static ZigType *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstNode *node,
2558 ErrorTableEntry *err_entry)
2559{
2560 ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
2561 buf_resize(&err_set_type->name, 0);
2562 buf_appendf(&err_set_type->name, "error{%s}", buf_ptr(&err_entry->name));
2563 err_set_type->size_in_bits = g->builtin_types.entry_global_error_set->size_in_bits;
2564 err_set_type->abi_align = g->builtin_types.entry_global_error_set->abi_align;
2565 err_set_type->abi_size = g->builtin_types.entry_global_error_set->abi_size;
2566 err_set_type->data.error_set.err_count = 1;
2567 err_set_type->data.error_set.errors = heap::c_allocator.create<ErrorTableEntry *>();
2568
2569 err_set_type->data.error_set.errors[0] = err_entry;
2570
2571 return err_set_type;
2572}
2573
2574static void invalidate_exec_gen(Stage1Air *exec, ErrorMsg *msg) {
2575 if (exec->first_err_trace_msg != nullptr)
2576 return;
2577
2578 exec->first_err_trace_msg = msg;
2579
2580 for (size_t i = 0; i < exec->tld_list.length; i += 1) {
2581 exec->tld_list.items[i]->resolution = TldResolutionInvalid;
2582 }
2583
2584 if (exec->source_exec != nullptr)
2585 invalidate_exec(exec->source_exec, msg);
2586}
2587
2588
2589static ErrorMsg *exec_add_error_node_gen(CodeGen *codegen, Stage1Air *exec, AstNode *source_node, Buf *msg) {
2590 ErrorMsg *err_msg = add_node_error(codegen, source_node, msg);
2591 invalidate_exec_gen(exec, err_msg);
2592 if (exec->parent_exec) {
2593 ir_add_call_stack_errors_gen(codegen, exec, err_msg, 10);
2594 }
2595 return err_msg;
2596}
2597
2598static ErrorMsg *ir_add_error_node(IrAnalyze *ira, AstNode *source_node, Buf *msg) {
2599 return exec_add_error_node_gen(ira->codegen, ira->new_irb.exec, source_node, msg);
2600}
2601
2602static ErrorMsg *opt_ir_add_error_node(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, Buf *msg) {
2603 if (ira != nullptr)
2604 return exec_add_error_node_gen(codegen, ira->new_irb.exec, source_node, msg);
2605 else
2606 return add_node_error(codegen, source_node, msg);
2607}
2608
2609static ErrorMsg *ir_add_error(IrAnalyze *ira, Stage1AirInst *source_instruction, Buf *msg) {
2610 return ir_add_error_node(ira, source_instruction->source_node, msg);
2611}
2612
2613// This function takes a comptime ptr and makes the child const value conform to the type
2614// described by the pointer.
2615static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
2616 ZigValue *ptr_val)
2617{
2618 Error err;
2619 assert(ptr_val->type->id == ZigTypeIdPointer);
2620 assert(ptr_val->special == ConstValSpecialStatic);
2621 ZigValue tmp = {};
2622 tmp.special = ConstValSpecialStatic;
2623 tmp.type = ptr_val->type->data.pointer.child_type;
2624 if ((err = ir_read_const_ptr(ira, codegen, source_node, &tmp, ptr_val)))
2625 return err;
2626 ZigValue *child_val = const_ptr_pointee_unchecked(codegen, ptr_val);
2627 copy_const_val(codegen, child_val, &tmp);
2628 return ErrorNone;
2629}
2630
2631ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val,
2632 AstNode *source_node)
2633{
2634 Error err;
2635 ZigValue *val = const_ptr_pointee_unchecked(codegen, const_val);
2636 if (val == nullptr) return nullptr;
2637 assert(const_val->type->id == ZigTypeIdPointer);
2638 ZigType *expected_type = const_val->type->data.pointer.child_type;
2639 if (expected_type == codegen->builtin_types.entry_anytype) {
2640 return val;
2641 }
2642 switch (type_has_one_possible_value(codegen, expected_type)) {
2643 case OnePossibleValueInvalid:
2644 return nullptr;
2645 case OnePossibleValueNo:
2646 break;
2647 case OnePossibleValueYes:
2648 return get_the_one_possible_value(codegen, expected_type);
2649 }
2650 if (!types_have_same_zig_comptime_repr(codegen, expected_type, val->type)) {
2651 if ((err = eval_comptime_ptr_reinterpret(ira, codegen, source_node, const_val)))
2652 return nullptr;
2653 return const_ptr_pointee_unchecked(codegen, const_val);
2654 }
2655 return val;
2656}
2657
2658static Error ir_exec_scan_for_side_effects(CodeGen *codegen, Stage1Air *exec) {
2659 Stage1AirBasicBlock *bb = exec->basic_block_list.at(0);
2660 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
2661 Stage1AirInst *instruction = bb->instruction_list.at(i);
2662 if (instruction->id == Stage1AirInstIdReturn) {
2663 return ErrorNone;
2664 } else if (ir_inst_gen_has_side_effects(instruction)) {
2665 if (instr_is_comptime(instruction)) {
2666 switch (instruction->id) {
2667 case Stage1AirInstIdUnwrapErrPayload:
2668 case Stage1AirInstIdOptionalUnwrapPtr:
2669 case Stage1AirInstIdUnionFieldPtr:
2670 continue;
2671 default:
2672 break;
2673 }
2674 }
2675 if (get_scope_typeof(instruction->scope) != nullptr) {
2676 // doesn't count, it's inside a @TypeOf()
2677 continue;
2678 }
2679 exec_add_error_node_gen(codegen, exec, instruction->source_node,
2680 buf_sprintf("unable to evaluate constant expression"));
2681 return ErrorSemanticAnalyzeFail;
2682 }
2683 }
2684 zig_unreachable();
2685}
2686
2687static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, Stage1ZirInst* source_instruction) {
2688 if (ir_should_inline(ira->zir, source_instruction->scope)) {
2689 ir_add_error_node(ira, source_instruction->source_node, buf_sprintf("unable to evaluate constant expression"));
2690 return false;
2691 }
2692 return true;
2693}
2694
2695static bool const_val_fits_in_num_lit(ZigValue *const_val, ZigType *num_lit_type) {
2696 return ((num_lit_type->id == ZigTypeIdComptimeFloat &&
2697 (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat)) ||
2698 (num_lit_type->id == ZigTypeIdComptimeInt &&
2699 (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt)));
2700}
2701
2702static bool float_has_fraction(ZigValue *const_val) {
2703 if (const_val->type->id == ZigTypeIdComptimeFloat) {
2704 return bigfloat_has_fraction(&const_val->data.x_bigfloat);
2705 } else if (const_val->type->id == ZigTypeIdFloat) {
2706 switch (const_val->type->data.floating.bit_count) {
2707 case 16:
2708 {
2709 float16_t floored = f16_roundToInt(const_val->data.x_f16, softfloat_round_minMag, false);
2710 return !f16_eq(floored, const_val->data.x_f16);
2711 }
2712 case 32:
2713 return floorf(const_val->data.x_f32) != const_val->data.x_f32;
2714 case 64:
2715 return floor(const_val->data.x_f64) != const_val->data.x_f64;
2716 case 80:
2717 {
2718 extFloat80_t floored;
2719 extF80M_roundToInt(&const_val->data.x_f80, softfloat_round_minMag, false, &floored);
2720 return !extF80M_eq(&floored, &const_val->data.x_f80);
2721 }
2722 case 128:
2723 {
2724 float128_t floored;
2725 f128M_roundToInt(&const_val->data.x_f128, softfloat_round_minMag, false, &floored);
2726 return !f128M_eq(&floored, &const_val->data.x_f128);
2727 }
2728 default:
2729 zig_unreachable();
2730 }
2731 } else {
2732 zig_unreachable();
2733 }
2734}
2735
2736static void float_append_buf(Buf *buf, ZigValue *const_val) {
2737 if (const_val->type->id == ZigTypeIdComptimeFloat) {
2738 bigfloat_append_buf(buf, &const_val->data.x_bigfloat);
2739 } else if (const_val->type->id == ZigTypeIdFloat) {
2740 switch (const_val->type->data.floating.bit_count) {
2741 case 16:
2742 buf_appendf(buf, "%f", zig_f16_to_double(const_val->data.x_f16));
2743 break;
2744 case 32:
2745 buf_appendf(buf, "%f", const_val->data.x_f32);
2746 break;
2747 case 64:
2748 buf_appendf(buf, "%f", const_val->data.x_f64);
2749 break;
2750 case 80:
2751 {
2752 float64_t f64_value = extF80M_to_f64(&const_val->data.x_f80);
2753 double double_value;
2754 memcpy(&double_value, &f64_value, sizeof(double));
2755
2756 buf_appendf(buf, "%f", const_val->data.x_f64);
2757 break;
2758 }
2759 case 128:
2760 {
2761 // TODO actual implementation
2762 const size_t extra_len = 100;
2763 size_t old_len = buf_len(buf);
2764 buf_resize(buf, old_len + extra_len);
2765
2766 float64_t f64_value = f128M_to_f64(&const_val->data.x_f128);
2767 double double_value;
2768 memcpy(&double_value, &f64_value, sizeof(double));
2769
2770 int len = snprintf(buf_ptr(buf) + old_len, extra_len, "%f", double_value);
2771 assert(len > 0);
2772 buf_resize(buf, old_len + len);
2773 break;
2774 }
2775 default:
2776 zig_unreachable();
2777 }
2778 } else {
2779 zig_unreachable();
2780 }
2781}
2782
2783static void float_init_bigint(BigInt *bigint, ZigValue *const_val) {
2784 if (const_val->type->id == ZigTypeIdComptimeFloat) {
2785 bigint_init_bigfloat(bigint, &const_val->data.x_bigfloat);
2786 } else if (const_val->type->id == ZigTypeIdFloat) {
2787 switch (const_val->type->data.floating.bit_count) {
2788 case 16:
2789 {
2790 double x = zig_f16_to_double(const_val->data.x_f16);
2791 if (x >= 0) {
2792 bigint_init_unsigned(bigint, (uint64_t)x);
2793 } else {
2794 bigint_init_unsigned(bigint, (uint64_t)-x);
2795 bigint->is_negative = true;
2796 }
2797 break;
2798 }
2799 case 32:
2800 if (const_val->data.x_f32 >= 0) {
2801 bigint_init_unsigned(bigint, (uint64_t)(const_val->data.x_f32));
2802 } else {
2803 bigint_init_unsigned(bigint, (uint64_t)(-const_val->data.x_f32));
2804 bigint->is_negative = true;
2805 }
2806 break;
2807 case 64:
2808 if (const_val->data.x_f64 >= 0) {
2809 bigint_init_unsigned(bigint, (uint64_t)(const_val->data.x_f64));
2810 } else {
2811 bigint_init_unsigned(bigint, (uint64_t)(-const_val->data.x_f64));
2812 bigint->is_negative = true;
2813 }
2814 break;
2815 case 80:
2816 {
2817 float128_t f128_value;
2818 extF80M_to_f128M(&const_val->data.x_f80, &f128_value);
2819 BigFloat tmp_float;
2820 bigfloat_init_128(&tmp_float, f128_value);
2821 bigint_init_bigfloat(bigint, &tmp_float);
2822 }
2823 break;
2824 case 128:
2825 {
2826 BigFloat tmp_float;
2827 bigfloat_init_128(&tmp_float, const_val->data.x_f128);
2828 bigint_init_bigfloat(bigint, &tmp_float);
2829 }
2830 break;
2831 default:
2832 zig_unreachable();
2833 }
2834 } else {
2835 zig_unreachable();
2836 }
2837}
2838
2839static void float_init_bigfloat(ZigValue *dest_val, BigFloat *bigfloat) {
2840 if (dest_val->type->id == ZigTypeIdComptimeFloat) {
2841 bigfloat_init_bigfloat(&dest_val->data.x_bigfloat, bigfloat);
2842 } else if (dest_val->type->id == ZigTypeIdFloat) {
2843 switch (dest_val->type->data.floating.bit_count) {
2844 case 16:
2845 dest_val->data.x_f16 = bigfloat_to_f16(bigfloat);
2846 break;
2847 case 32:
2848 dest_val->data.x_f32 = bigfloat_to_f32(bigfloat);
2849 break;
2850 case 64:
2851 dest_val->data.x_f64 = bigfloat_to_f64(bigfloat);
2852 break;
2853 case 80: {
2854 float128_t f128_value = bigfloat_to_f128(bigfloat);
2855 f128M_to_extF80M(&f128_value, &dest_val->data.x_f80);
2856 break;
2857 }
2858 case 128:
2859 dest_val->data.x_f128 = bigfloat_to_f128(bigfloat);
2860 break;
2861 default:
2862 zig_unreachable();
2863 }
2864 } else {
2865 zig_unreachable();
2866 }
2867}
2868
2869static void float_init_f16(ZigValue *dest_val, float16_t x) {
2870 if (dest_val->type->id == ZigTypeIdComptimeFloat) {
2871 bigfloat_init_16(&dest_val->data.x_bigfloat, x);
2872 } else if (dest_val->type->id == ZigTypeIdFloat) {
2873 switch (dest_val->type->data.floating.bit_count) {
2874 case 16:
2875 dest_val->data.x_f16 = x;
2876 break;
2877 case 32:
2878 dest_val->data.x_f32 = zig_f16_to_double(x);
2879 break;
2880 case 64:
2881 dest_val->data.x_f64 = zig_f16_to_double(x);
2882 break;
2883 case 80:
2884 f16_to_extF80M(x, &dest_val->data.x_f80);
2885 break;
2886 case 128:
2887 f16_to_f128M(x, &dest_val->data.x_f128);
2888 break;
2889 default:
2890 zig_unreachable();
2891 }
2892 } else {
2893 zig_unreachable();
2894 }
2895}
2896
2897static void float_init_f32(ZigValue *dest_val, float x) {
2898 if (dest_val->type->id == ZigTypeIdComptimeFloat) {
2899 bigfloat_init_32(&dest_val->data.x_bigfloat, x);
2900 } else if (dest_val->type->id == ZigTypeIdFloat) {
2901 switch (dest_val->type->data.floating.bit_count) {
2902 case 16:
2903 dest_val->data.x_f16 = zig_double_to_f16(x);
2904 break;
2905 case 32:
2906 dest_val->data.x_f32 = x;
2907 break;
2908 case 64:
2909 dest_val->data.x_f64 = x;
2910 break;
2911 case 80: {
2912 float32_t x_f32;
2913 memcpy(&x_f32, &x, sizeof(float));
2914 f32_to_extF80M(x_f32, &dest_val->data.x_f80);
2915 break;
2916 }
2917 case 128:
2918 {
2919 float32_t x_f32;
2920 memcpy(&x_f32, &x, sizeof(float));
2921 f32_to_f128M(x_f32, &dest_val->data.x_f128);
2922 break;
2923 }
2924 default:
2925 zig_unreachable();
2926 }
2927 } else {
2928 zig_unreachable();
2929 }
2930}
2931
2932static void float_init_f64(ZigValue *dest_val, double x) {
2933 if (dest_val->type->id == ZigTypeIdComptimeFloat) {
2934 bigfloat_init_64(&dest_val->data.x_bigfloat, x);
2935 } else if (dest_val->type->id == ZigTypeIdFloat) {
2936 switch (dest_val->type->data.floating.bit_count) {
2937 case 16:
2938 dest_val->data.x_f16 = zig_double_to_f16(x);
2939 break;
2940 case 32:
2941 dest_val->data.x_f32 = x;
2942 break;
2943 case 64:
2944 dest_val->data.x_f64 = x;
2945 break;
2946 case 80: {
2947 float64_t x_f64;
2948 memcpy(&x_f64, &x, sizeof(double));
2949 f64_to_extF80M(x_f64, &dest_val->data.x_f80);
2950 break;
2951 }
2952 case 128:
2953 {
2954 float64_t x_f64;
2955 memcpy(&x_f64, &x, sizeof(double));
2956 f64_to_f128M(x_f64, &dest_val->data.x_f128);
2957 break;
2958 }
2959 default:
2960 zig_unreachable();
2961 }
2962 } else {
2963 zig_unreachable();
2964 }
2965}
2966
2967static void float_init_f128(ZigValue *dest_val, float128_t x) {
2968 if (dest_val->type->id == ZigTypeIdComptimeFloat) {
2969 bigfloat_init_128(&dest_val->data.x_bigfloat, x);
2970 } else if (dest_val->type->id == ZigTypeIdFloat) {
2971 switch (dest_val->type->data.floating.bit_count) {
2972 case 16:
2973 dest_val->data.x_f16 = f128M_to_f16(&x);
2974 break;
2975 case 32:
2976 {
2977 float32_t f32_val = f128M_to_f32(&x);
2978 memcpy(&dest_val->data.x_f32, &f32_val, sizeof(float));
2979 break;
2980 }
2981 case 64:
2982 {
2983 float64_t f64_val = f128M_to_f64(&x);
2984 memcpy(&dest_val->data.x_f64, &f64_val, sizeof(double));
2985 break;
2986 }
2987 case 80:
2988 f128M_to_extF80M(&x, &dest_val->data.x_f80);
2989 break;
2990 case 128:
2991 {
2992 memcpy(&dest_val->data.x_f128, &x, sizeof(float128_t));
2993 break;
2994 }
2995 default:
2996 zig_unreachable();
2997 }
2998 } else {
2999 zig_unreachable();
3000 }
3001}
3002
3003static void float_init_float(ZigValue *dest_val, ZigValue *src_val) {
3004 if (src_val->type->id == ZigTypeIdComptimeFloat) {
3005 float_init_bigfloat(dest_val, &src_val->data.x_bigfloat);
3006 } else if (src_val->type->id == ZigTypeIdFloat) {
3007 switch (src_val->type->data.floating.bit_count) {
3008 case 16:
3009 float_init_f16(dest_val, src_val->data.x_f16);
3010 break;
3011 case 32:
3012 float_init_f32(dest_val, src_val->data.x_f32);
3013 break;
3014 case 64:
3015 float_init_f64(dest_val, src_val->data.x_f64);
3016 break;
3017 case 80: {
3018 float128_t f128_value;
3019 extF80M_to_f128M(&src_val->data.x_f80, &f128_value);
3020 float_init_f128(dest_val, f128_value);
3021 break;
3022 }
3023 case 128:
3024 float_init_f128(dest_val, src_val->data.x_f128);
3025 break;
3026 default:
3027 zig_unreachable();
3028 }
3029 } else {
3030 zig_unreachable();
3031 }
3032}
3033
3034static bool float_is_nan(ZigValue *op) {
3035 if (op->type->id == ZigTypeIdComptimeFloat) {
3036 return bigfloat_is_nan(&op->data.x_bigfloat);
3037 } else if (op->type->id == ZigTypeIdFloat) {
3038 switch (op->type->data.floating.bit_count) {
3039 case 16:
3040 return zig_f16_isNaN(op->data.x_f16);
3041 case 32:
3042 return op->data.x_f32 != op->data.x_f32;
3043 case 64:
3044 return op->data.x_f64 != op->data.x_f64;
3045 case 80:
3046 return zig_extF80_isNaN(&op->data.x_f80);
3047 case 128:
3048 return zig_f128_isNaN(&op->data.x_f128);
3049 default:
3050 zig_unreachable();
3051 }
3052 } else {
3053 zig_unreachable();
3054 }
3055}
3056
3057static Cmp float_cmp(ZigValue *op1, ZigValue *op2) {
3058 if (op1->type == op2->type) {
3059 if (op1->type->id == ZigTypeIdComptimeFloat) {
3060 return bigfloat_cmp(&op1->data.x_bigfloat, &op2->data.x_bigfloat);
3061 } else if (op1->type->id == ZigTypeIdFloat) {
3062 switch (op1->type->data.floating.bit_count) {
3063 case 16:
3064 if (f16_lt(op1->data.x_f16, op2->data.x_f16)) {
3065 return CmpLT;
3066 } else if (f16_lt(op2->data.x_f16, op1->data.x_f16)) {
3067 return CmpGT;
3068 } else {
3069 return CmpEQ;
3070 }
3071 case 32:
3072 if (op1->data.x_f32 > op2->data.x_f32) {
3073 return CmpGT;
3074 } else if (op1->data.x_f32 < op2->data.x_f32) {
3075 return CmpLT;
3076 } else {
3077 return CmpEQ;
3078 }
3079 case 64:
3080 if (op1->data.x_f64 > op2->data.x_f64) {
3081 return CmpGT;
3082 } else if (op1->data.x_f64 < op2->data.x_f64) {
3083 return CmpLT;
3084 } else {
3085 return CmpEQ;
3086 }
3087 case 80:
3088 if (extF80M_lt(&op1->data.x_f80, &op2->data.x_f80)) {
3089 return CmpLT;
3090 } else if (extF80M_eq(&op1->data.x_f80, &op2->data.x_f80)) {
3091 return CmpEQ;
3092 } else {
3093 return CmpGT;
3094 }
3095 case 128:
3096 if (f128M_lt(&op1->data.x_f128, &op2->data.x_f128)) {
3097 return CmpLT;
3098 } else if (f128M_eq(&op1->data.x_f128, &op2->data.x_f128)) {
3099 return CmpEQ;
3100 } else {
3101 return CmpGT;
3102 }
3103 default:
3104 zig_unreachable();
3105 }
3106 } else {
3107 zig_unreachable();
3108 }
3109 }
3110 BigFloat op1_big;
3111 BigFloat op2_big;
3112 value_to_bigfloat(&op1_big, op1);
3113 value_to_bigfloat(&op2_big, op2);
3114 return bigfloat_cmp(&op1_big, &op2_big);
3115}
3116
3117// This function cannot handle NaN
3118static Cmp float_cmp_zero(ZigValue *op) {
3119 if (op->type->id == ZigTypeIdComptimeFloat) {
3120 return bigfloat_cmp_zero(&op->data.x_bigfloat);
3121 } else if (op->type->id == ZigTypeIdFloat) {
3122 switch (op->type->data.floating.bit_count) {
3123 case 16:
3124 {
3125 const float16_t zero = zig_double_to_f16(0);
3126 if (f16_lt(op->data.x_f16, zero)) {
3127 return CmpLT;
3128 } else if (f16_lt(zero, op->data.x_f16)) {
3129 return CmpGT;
3130 } else {
3131 return CmpEQ;
3132 }
3133 }
3134 case 32:
3135 if (op->data.x_f32 < 0.0) {
3136 return CmpLT;
3137 } else if (op->data.x_f32 > 0.0) {
3138 return CmpGT;
3139 } else {
3140 return CmpEQ;
3141 }
3142 case 64:
3143 if (op->data.x_f64 < 0.0) {
3144 return CmpLT;
3145 } else if (op->data.x_f64 > 0.0) {
3146 return CmpGT;
3147 } else {
3148 return CmpEQ;
3149 }
3150 case 80: {
3151 extFloat80_t zero_float;
3152 ui32_to_extF80M(0, &zero_float);
3153 if (extF80M_lt(&op->data.x_f80, &zero_float)) {
3154 return CmpLT;
3155 } else if (extF80M_eq(&op->data.x_f80, &zero_float)) {
3156 return CmpEQ;
3157 } else {
3158 return CmpGT;
3159 }
3160 }
3161 case 128: {
3162 float128_t zero_float;
3163 ui32_to_f128M(0, &zero_float);
3164 if (f128M_lt(&op->data.x_f128, &zero_float)) {
3165 return CmpLT;
3166 } else if (f128M_eq(&op->data.x_f128, &zero_float)) {
3167 return CmpEQ;
3168 } else {
3169 return CmpGT;
3170 }
3171 }
3172 default:
3173 zig_unreachable();
3174 }
3175 } else {
3176 zig_unreachable();
3177 }
3178}
3179
3180static void float_add(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3181 assert(op1->type == op2->type);
3182 out_val->type = op1->type;
3183 if (op1->type->id == ZigTypeIdComptimeFloat) {
3184 bigfloat_add(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
3185 } else if (op1->type->id == ZigTypeIdFloat) {
3186 switch (op1->type->data.floating.bit_count) {
3187 case 16:
3188 out_val->data.x_f16 = f16_add(op1->data.x_f16, op2->data.x_f16);
3189 return;
3190 case 32:
3191 out_val->data.x_f32 = op1->data.x_f32 + op2->data.x_f32;
3192 return;
3193 case 64:
3194 out_val->data.x_f64 = op1->data.x_f64 + op2->data.x_f64;
3195 return;
3196 case 80:
3197 extF80M_add(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3198 return;
3199 case 128:
3200 f128M_add(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3201 return;
3202 default:
3203 zig_unreachable();
3204 }
3205 } else {
3206 zig_unreachable();
3207 }
3208}
3209
3210static void float_sub(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3211 assert(op1->type == op2->type);
3212 out_val->type = op1->type;
3213 if (op1->type->id == ZigTypeIdComptimeFloat) {
3214 bigfloat_sub(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
3215 } else if (op1->type->id == ZigTypeIdFloat) {
3216 switch (op1->type->data.floating.bit_count) {
3217 case 16:
3218 out_val->data.x_f16 = f16_sub(op1->data.x_f16, op2->data.x_f16);
3219 return;
3220 case 32:
3221 out_val->data.x_f32 = op1->data.x_f32 - op2->data.x_f32;
3222 return;
3223 case 64:
3224 out_val->data.x_f64 = op1->data.x_f64 - op2->data.x_f64;
3225 return;
3226 case 80:
3227 extF80M_sub(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3228 return;
3229 case 128:
3230 f128M_sub(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3231 return;
3232 default:
3233 zig_unreachable();
3234 }
3235 } else {
3236 zig_unreachable();
3237 }
3238}
3239
3240static void float_mul(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3241 assert(op1->type == op2->type);
3242 out_val->type = op1->type;
3243 if (op1->type->id == ZigTypeIdComptimeFloat) {
3244 bigfloat_mul(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
3245 } else if (op1->type->id == ZigTypeIdFloat) {
3246 switch (op1->type->data.floating.bit_count) {
3247 case 16:
3248 out_val->data.x_f16 = f16_mul(op1->data.x_f16, op2->data.x_f16);
3249 return;
3250 case 32:
3251 out_val->data.x_f32 = op1->data.x_f32 * op2->data.x_f32;
3252 return;
3253 case 64:
3254 out_val->data.x_f64 = op1->data.x_f64 * op2->data.x_f64;
3255 return;
3256 case 80:
3257 extF80M_mul(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3258 return;
3259 case 128:
3260 f128M_mul(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3261 return;
3262 default:
3263 zig_unreachable();
3264 }
3265 } else {
3266 zig_unreachable();
3267 }
3268}
3269
3270static void float_div(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3271 assert(op1->type == op2->type);
3272 out_val->type = op1->type;
3273 if (op1->type->id == ZigTypeIdComptimeFloat) {
3274 bigfloat_div(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
3275 } else if (op1->type->id == ZigTypeIdFloat) {
3276 switch (op1->type->data.floating.bit_count) {
3277 case 16:
3278 out_val->data.x_f16 = f16_div(op1->data.x_f16, op2->data.x_f16);
3279 return;
3280 case 32:
3281 out_val->data.x_f32 = op1->data.x_f32 / op2->data.x_f32;
3282 return;
3283 case 64:
3284 out_val->data.x_f64 = op1->data.x_f64 / op2->data.x_f64;
3285 return;
3286 case 80:
3287 extF80M_div(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3288 return;
3289 case 128:
3290 f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3291 return;
3292 default:
3293 zig_unreachable();
3294 }
3295 } else {
3296 zig_unreachable();
3297 }
3298}
3299
3300static void float_div_trunc(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3301 assert(op1->type == op2->type);
3302 out_val->type = op1->type;
3303 if (op1->type->id == ZigTypeIdComptimeFloat) {
3304 bigfloat_div_trunc(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
3305 } else if (op1->type->id == ZigTypeIdFloat) {
3306 switch (op1->type->data.floating.bit_count) {
3307 case 16:
3308 out_val->data.x_f16 = f16_div(op1->data.x_f16, op2->data.x_f16);
3309 out_val->data.x_f16 = f16_roundToInt(out_val->data.x_f16, softfloat_round_minMag, false);
3310 return;
3311 case 32:
3312 out_val->data.x_f32 = truncf(op1->data.x_f32 / op2->data.x_f32);
3313 return;
3314 case 64:
3315 out_val->data.x_f64 = trunc(op1->data.x_f64 / op2->data.x_f64);
3316 return;
3317 case 80:
3318 extF80M_div(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3319 extF80M_roundToInt(&out_val->data.x_f80, softfloat_round_minMag, false, &out_val->data.x_f80);
3320 return;
3321 case 128:
3322 f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3323 f128M_roundToInt(&out_val->data.x_f128, softfloat_round_minMag, false, &out_val->data.x_f128);
3324 return;
3325 default:
3326 zig_unreachable();
3327 }
3328 } else {
3329 zig_unreachable();
3330 }
3331}
3332
3333static void float_div_floor(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3334 assert(op1->type == op2->type);
3335 out_val->type = op1->type;
3336 if (op1->type->id == ZigTypeIdComptimeFloat) {
3337 bigfloat_div_floor(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
3338 } else if (op1->type->id == ZigTypeIdFloat) {
3339 switch (op1->type->data.floating.bit_count) {
3340 case 16:
3341 out_val->data.x_f16 = f16_div(op1->data.x_f16, op2->data.x_f16);
3342 out_val->data.x_f16 = f16_roundToInt(out_val->data.x_f16, softfloat_round_min, false);
3343 return;
3344 case 32:
3345 out_val->data.x_f32 = floorf(op1->data.x_f32 / op2->data.x_f32);
3346 return;
3347 case 64:
3348 out_val->data.x_f64 = floor(op1->data.x_f64 / op2->data.x_f64);
3349 return;
3350 case 80:
3351 extF80M_div(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3352 extF80M_roundToInt(&out_val->data.x_f80, softfloat_round_min, false, &out_val->data.x_f80);
3353 return;
3354 case 128:
3355 f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3356 f128M_roundToInt(&out_val->data.x_f128, softfloat_round_min, false, &out_val->data.x_f128);
3357 return;
3358 default:
3359 zig_unreachable();
3360 }
3361 } else {
3362 zig_unreachable();
3363 }
3364}
3365
3366// c = a - b * trunc(a / b)
3367static float16_t zig_f16_rem(float16_t a, float16_t b) {
3368 float16_t c;
3369 c = f16_div(a, b);
3370 c = f16_roundToInt(c, softfloat_round_minMag, false);
3371 c = f16_mul(b, c);
3372 c = f16_sub(a, c);
3373 return c;
3374}
3375
3376// c = a - b * trunc(a / b)
3377static void zig_f128M_rem(const float128_t* a, const float128_t* b, float128_t* c) {
3378 f128M_div(a, b, c);
3379 f128M_roundToInt(c, softfloat_round_minMag, false, c);
3380 f128M_mul(b, c, c);
3381 f128M_sub(a, c, c);
3382}
3383
3384// c = a - b * trunc(a / b)
3385static void zig_extF80M_rem(const extFloat80_t* a, const extFloat80_t* b, extFloat80_t* c) {
3386 extF80M_div(a, b, c);
3387 extF80M_roundToInt(c, softfloat_round_minMag, false, c);
3388 extF80M_mul(b, c, c);
3389 extF80M_sub(a, c, c);
3390}
3391
3392static void float_rem(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3393 assert(op1->type == op2->type);
3394 out_val->type = op1->type;
3395 if (op1->type->id == ZigTypeIdComptimeFloat) {
3396 bigfloat_rem(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
3397 } else if (op1->type->id == ZigTypeIdFloat) {
3398 switch (op1->type->data.floating.bit_count) {
3399 case 16:
3400 out_val->data.x_f16 = zig_f16_rem(op1->data.x_f16, op2->data.x_f16);
3401 return;
3402 case 32:
3403 out_val->data.x_f32 = fmodf(op1->data.x_f32, op2->data.x_f32);
3404 return;
3405 case 64:
3406 out_val->data.x_f64 = fmod(op1->data.x_f64, op2->data.x_f64);
3407 return;
3408 case 80:
3409 zig_extF80M_rem(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3410 return;
3411 case 128:
3412 zig_f128M_rem(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3413 return;
3414 default:
3415 zig_unreachable();
3416 }
3417 } else {
3418 zig_unreachable();
3419 }
3420}
3421
3422// c = a - b * trunc(a / b)
3423static float16_t zig_f16_mod(float16_t a, float16_t b) {
3424 float16_t c;
3425 c = f16_div(a, b);
3426 c = f16_roundToInt(c, softfloat_round_min, true);
3427 c = f16_mul(b, c);
3428 c = f16_sub(a, c);
3429 return c;
3430}
3431
3432// c = a - b * trunc(a / b)
3433static void zig_f128M_mod(const float128_t* a, const float128_t* b, float128_t* c) {
3434 f128M_div(a, b, c);
3435 f128M_roundToInt(c, softfloat_round_min, true, c);
3436 f128M_mul(b, c, c);
3437 f128M_sub(a, c, c);
3438}
3439
3440// c = a - b * trunc(a / b)
3441static void zig_extF80M_mod(const extFloat80_t* a, const extFloat80_t* b, extFloat80_t* c) {
3442 extF80M_div(a, b, c);
3443 extF80M_roundToInt(c, softfloat_round_min, true, c);
3444 extF80M_mul(b, c, c);
3445 extF80M_sub(a, c, c);
3446}
3447
3448static void float_mod(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3449 assert(op1->type == op2->type);
3450 out_val->type = op1->type;
3451 if (op1->type->id == ZigTypeIdComptimeFloat) {
3452 bigfloat_mod(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
3453 } else if (op1->type->id == ZigTypeIdFloat) {
3454 switch (op1->type->data.floating.bit_count) {
3455 case 16:
3456 out_val->data.x_f16 = zig_f16_mod(op1->data.x_f16, op2->data.x_f16);
3457 return;
3458 case 32:
3459 out_val->data.x_f32 = fmodf(fmodf(op1->data.x_f32, op2->data.x_f32) + op2->data.x_f32, op2->data.x_f32);
3460 return;
3461 case 64:
3462 out_val->data.x_f64 = fmod(fmod(op1->data.x_f64, op2->data.x_f64) + op2->data.x_f64, op2->data.x_f64);
3463 return;
3464 case 80:
3465 zig_extF80M_mod(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3466 return;
3467 case 128:
3468 zig_f128M_mod(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3469 return;
3470 default:
3471 zig_unreachable();
3472 }
3473 } else {
3474 zig_unreachable();
3475 }
3476}
3477
3478static void float_max(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3479 assert(op1->type == op2->type);
3480 out_val->type = op1->type;
3481 if (op1->type->id == ZigTypeIdComptimeFloat) {
3482 bigfloat_max(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
3483 } else if (op1->type->id == ZigTypeIdFloat) {
3484 switch (op1->type->data.floating.bit_count) {
3485 case 16:
3486 if (zig_f16_isNaN(op1->data.x_f16)) {
3487 out_val->data.x_f16 = op2->data.x_f16;
3488 } else if (zig_f16_isNaN(op2->data.x_f16)) {
3489 out_val->data.x_f16 = op1->data.x_f16;
3490 } else {
3491 out_val->data.x_f16 = f16_lt(op1->data.x_f16, op2->data.x_f16) ? op2->data.x_f16 : op1->data.x_f16;
3492 }
3493 return;
3494 case 32:
3495 if (op1->data.x_f32 != op1->data.x_f32) {
3496 out_val->data.x_f32 = op2->data.x_f32;
3497 } else if (op2->data.x_f32 != op2->data.x_f32) {
3498 out_val->data.x_f32 = op1->data.x_f32;
3499 } else {
3500 out_val->data.x_f32 = op1->data.x_f32 > op2->data.x_f32 ? op1->data.x_f32 : op2->data.x_f32;
3501 }
3502 return;
3503 case 64:
3504 if (op1->data.x_f64 != op1->data.x_f64) {
3505 out_val->data.x_f64 = op2->data.x_f64;
3506 } else if (op2->data.x_f64 != op2->data.x_f64) {
3507 out_val->data.x_f64 = op1->data.x_f64;
3508 } else {
3509 out_val->data.x_f64 = op1->data.x_f64 > op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64;
3510 }
3511 return;
3512 case 80:
3513 if (zig_extF80_isNaN(&op1->data.x_f80)) {
3514 out_val->data.x_f80 = op2->data.x_f80;
3515 } else if (zig_extF80_isNaN(&op2->data.x_f80)) {
3516 out_val->data.x_f80 = op1->data.x_f80;
3517 } else {
3518 out_val->data.x_f80 = extF80M_lt(&op1->data.x_f80, &op2->data.x_f80) ? op2->data.x_f80 : op1->data.x_f80;
3519 }
3520 return;
3521 case 128:
3522 if (zig_f128_isNaN(&op1->data.x_f128)) {
3523 out_val->data.x_f128 = op2->data.x_f128;
3524 } else if (zig_f128_isNaN(&op2->data.x_f128)) {
3525 out_val->data.x_f128 = op1->data.x_f128;
3526 } else {
3527 out_val->data.x_f128 = f128M_lt(&op1->data.x_f128, &op2->data.x_f128) ? op2->data.x_f128 : op1->data.x_f128;
3528 }
3529 return;
3530 default:
3531 zig_unreachable();
3532 }
3533 } else {
3534 zig_unreachable();
3535 }
3536}
3537
3538static void float_min(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3539 assert(op1->type == op2->type);
3540 out_val->type = op1->type;
3541 if (op1->type->id == ZigTypeIdComptimeFloat) {
3542 bigfloat_min(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat);
3543 } else if (op1->type->id == ZigTypeIdFloat) {
3544 switch (op1->type->data.floating.bit_count) {
3545 case 16:
3546 if (zig_f16_isNaN(op1->data.x_f16)) {
3547 out_val->data.x_f16 = op2->data.x_f16;
3548 } else if (zig_f16_isNaN(op2->data.x_f16)) {
3549 out_val->data.x_f16 = op1->data.x_f16;
3550 } else {
3551 out_val->data.x_f16 = f16_lt(op1->data.x_f16, op2->data.x_f16) ? op1->data.x_f16 : op2->data.x_f16;
3552 }
3553 return;
3554 case 32:
3555 if (op1->data.x_f32 != op1->data.x_f32) {
3556 out_val->data.x_f32 = op2->data.x_f32;
3557 } else if (op2->data.x_f32 != op2->data.x_f32) {
3558 out_val->data.x_f32 = op1->data.x_f32;
3559 } else {
3560 out_val->data.x_f32 = op1->data.x_f32 < op2->data.x_f32 ? op1->data.x_f32 : op2->data.x_f32;
3561 }
3562 return;
3563 case 64:
3564 if (op1->data.x_f64 != op1->data.x_f64) {
3565 out_val->data.x_f64 = op2->data.x_f64;
3566 } else if (op2->data.x_f64 != op2->data.x_f64) {
3567 out_val->data.x_f64 = op1->data.x_f64;
3568 } else {
3569 out_val->data.x_f64 = op1->data.x_f32 < op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64;
3570 }
3571 return;
3572 case 80:
3573 if (zig_extF80_isNaN(&op1->data.x_f80)) {
3574 out_val->data.x_f80 = op2->data.x_f80;
3575 } else if (zig_extF80_isNaN(&op2->data.x_f80)) {
3576 out_val->data.x_f80 = op1->data.x_f80;
3577 } else {
3578 out_val->data.x_f80 = extF80M_lt(&op1->data.x_f80, &op2->data.x_f80) ? op1->data.x_f80 : op2->data.x_f80;
3579 }
3580 return;
3581 case 128:
3582 if (zig_f128_isNaN(&op1->data.x_f128)) {
3583 out_val->data.x_f128 = op2->data.x_f128;
3584 } else if (zig_f128_isNaN(&op2->data.x_f128)) {
3585 out_val->data.x_f128 = op1->data.x_f128;
3586 } else {
3587 out_val->data.x_f128 = f128M_lt(&op1->data.x_f128, &op2->data.x_f128) ? op1->data.x_f128 : op2->data.x_f128;
3588 }
3589 return;
3590 default:
3591 zig_unreachable();
3592 }
3593 } else {
3594 zig_unreachable();
3595 }
3596}
3597
3598static void float_negate(ZigValue *out_val, ZigValue *op) {
3599 out_val->type = op->type;
3600 if (op->type->id == ZigTypeIdComptimeFloat) {
3601 bigfloat_negate(&out_val->data.x_bigfloat, &op->data.x_bigfloat);
3602 } else if (op->type->id == ZigTypeIdFloat) {
3603 switch (op->type->data.floating.bit_count) {
3604 case 16:
3605 out_val->data.x_f16 = f16_neg(op->data.x_f16);
3606 return;
3607 case 32:
3608 out_val->data.x_f32 = -op->data.x_f32;
3609 return;
3610 case 64:
3611 out_val->data.x_f64 = -op->data.x_f64;
3612 return;
3613 case 80:
3614 extF80M_neg(&op->data.x_f80, &out_val->data.x_f80);
3615 return;
3616 case 128:
3617 f128M_neg(&op->data.x_f128, &out_val->data.x_f128);
3618 return;
3619 default:
3620 zig_unreachable();
3621 }
3622 } else {
3623 zig_unreachable();
3624 }
3625}
3626
3627void float_write_ieee597(ZigValue *op, uint8_t *buf, bool target_is_big_endian) {
3628 if (op->type->id != ZigTypeIdFloat)
3629 zig_unreachable();
3630
3631 const unsigned n = op->type->data.floating.bit_count / 8;
3632 assert(n <= 16);
3633
3634 switch (op->type->data.floating.bit_count) {
3635 case 16:
3636 memcpy(buf, &op->data.x_f16, 2);
3637 break;
3638 case 32:
3639 memcpy(buf, &op->data.x_f32, 4);
3640 break;
3641 case 64:
3642 memcpy(buf, &op->data.x_f64, 8);
3643 break;
3644 case 80:
3645 memcpy(buf, &op->data.x_f80, 16);
3646 break;
3647 case 128:
3648 memcpy(buf, &op->data.x_f128, 16);
3649 break;
3650 default:
3651 zig_unreachable();
3652 }
3653
3654 // Byteswap if system endianness != target endianness
3655 if (native_is_big_endian != target_is_big_endian) {
3656 for (size_t i = 0; i < n / 2; i++) {
3657 uint8_t u = buf[i];
3658 buf[i] = buf[n - 1 - i];
3659 buf[n - 1 - i] = u;
3660 }
3661 }
3662}
3663
3664void float_read_ieee597(ZigValue *val, uint8_t *buf, bool target_is_big_endian) {
3665 if (val->type->id != ZigTypeIdFloat)
3666 zig_unreachable();
3667
3668 const unsigned n = val->type->data.floating.bit_count / 8;
3669 assert(n <= 16);
3670
3671 uint8_t tmp[16];
3672 uint8_t *ptr = buf;
3673
3674 // Byteswap if system endianness != target endianness
3675 if (native_is_big_endian != target_is_big_endian) {
3676 memcpy(tmp, buf, n);
3677 for (size_t i = 0; i < n / 2; i++) {
3678 uint8_t u = tmp[i];
3679 tmp[i] = tmp[n - 1 - i];
3680 tmp[n - 1 - i] = u;
3681 }
3682
3683 ptr = tmp;
3684 }
3685
3686 switch (val->type->data.floating.bit_count) {
3687 case 16:
3688 memcpy(&val->data.x_f16, ptr, 2);
3689 return;
3690 case 32:
3691 memcpy(&val->data.x_f32, ptr, 4);
3692 return;
3693 case 64:
3694 memcpy(&val->data.x_f64, ptr, 8);
3695 return;
3696 case 80:
3697 memcpy(&val->data.x_f80, ptr, 16);
3698 return;
3699 case 128:
3700 memcpy(&val->data.x_f128, ptr, 16);
3701 return;
3702 default:
3703 zig_unreachable();
3704 }
3705}
3706
3707static void value_to_bigfloat(BigFloat *out, ZigValue *val) {
3708 switch (val->type->id) {
3709 case ZigTypeIdInt:
3710 case ZigTypeIdComptimeInt:
3711 bigfloat_init_bigint(out, &val->data.x_bigint);
3712 return;
3713 case ZigTypeIdComptimeFloat:
3714 *out = val->data.x_bigfloat;
3715 return;
3716 case ZigTypeIdFloat: switch (val->type->data.floating.bit_count) {
3717 case 16:
3718 bigfloat_init_16(out, val->data.x_f16);
3719 return;
3720 case 32:
3721 bigfloat_init_32(out, val->data.x_f32);
3722 return;
3723 case 64:
3724 bigfloat_init_64(out, val->data.x_f64);
3725 return;
3726 case 80: {
3727 float128_t f128_value;
3728 extF80M_to_f128M(&val->data.x_f80, &f128_value);
3729 bigfloat_init_128(out, f128_value);
3730 return;
3731 }
3732 case 128:
3733 bigfloat_init_128(out, val->data.x_f128);
3734 return;
3735 default:
3736 zig_unreachable();
3737 }
3738 default:
3739 zig_unreachable();
3740 }
3741}
3742
3743static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruction, ZigType *other_type,
3744 bool explicit_cast)
3745{
3746 if (type_is_invalid(other_type)) {
3747 return false;
3748 }
3749
3750 ZigValue *const_val = ir_resolve_const(ira, instruction, LazyOkNoUndef);
3751 if (const_val == nullptr)
3752 return false;
3753
3754 if (const_val->special == ConstValSpecialLazy) {
3755 switch (const_val->data.x_lazy->id) {
3756 case LazyValueIdAlignOf: {
3757 // This is guaranteed to fit into a u29
3758 if (other_type->id == ZigTypeIdComptimeInt)
3759 return true;
3760 size_t align_bits = get_align_amt_type(ira->codegen)->data.integral.bit_count;
3761 if (other_type->id == ZigTypeIdInt && !other_type->data.integral.is_signed &&
3762 other_type->data.integral.bit_count >= align_bits)
3763 {
3764 return true;
3765 }
3766 break;
3767 }
3768 case LazyValueIdSizeOf: {
3769 // This is guaranteed to fit into a usize
3770 if (other_type->id == ZigTypeIdComptimeInt)
3771 return true;
3772 size_t usize_bits = ira->codegen->builtin_types.entry_usize->data.integral.bit_count;
3773 if (other_type->id == ZigTypeIdInt && !other_type->data.integral.is_signed &&
3774 other_type->data.integral.bit_count >= usize_bits)
3775 {
3776 return true;
3777 }
3778 break;
3779 }
3780 default:
3781 break;
3782 }
3783 }
3784
3785 const_val = ir_resolve_const(ira, instruction, UndefBad);
3786 if (const_val == nullptr)
3787 return false;
3788
3789 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);
3790 bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat);
3791 assert(const_val_is_int || const_val_is_float);
3792
3793 if (const_val_is_int && other_type->id == ZigTypeIdComptimeFloat) {
3794 return true;
3795 }
3796 if (other_type->id == ZigTypeIdFloat) {
3797 if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) {
3798 return true;
3799 }
3800 if (const_val->type->id == ZigTypeIdInt) {
3801 BigFloat tmp_bf;
3802 bigfloat_init_bigint(&tmp_bf, &const_val->data.x_bigint);
3803 BigFloat orig_bf;
3804 switch (other_type->data.floating.bit_count) {
3805 case 16: {
3806 float16_t tmp = bigfloat_to_f16(&tmp_bf);
3807 bigfloat_init_16(&orig_bf, tmp);
3808 break;
3809 }
3810 case 32: {
3811 float tmp = bigfloat_to_f32(&tmp_bf);
3812 bigfloat_init_32(&orig_bf, tmp);
3813 break;
3814 }
3815 case 64: {
3816 double tmp = bigfloat_to_f64(&tmp_bf);
3817 bigfloat_init_64(&orig_bf, tmp);
3818 break;
3819 }
3820 case 80: {
3821 float128_t tmp = bigfloat_to_f128(&tmp_bf);
3822 extFloat80_t tmp80;
3823 f128M_to_extF80M(&tmp, &tmp80);
3824 extF80M_to_f128M(&tmp80, &tmp);
3825 bigfloat_init_128(&orig_bf, tmp);
3826 break;
3827 }
3828 case 128: {
3829 float128_t tmp = bigfloat_to_f128(&tmp_bf);
3830 bigfloat_init_128(&orig_bf, tmp);
3831 break;
3832 }
3833 default:
3834 zig_unreachable();
3835 }
3836 BigInt orig_bi;
3837 bigint_init_bigfloat(&orig_bi, &orig_bf);
3838 if (bigint_cmp(&orig_bi, &const_val->data.x_bigint) == CmpEQ) {
3839 return true;
3840 }
3841 Buf *val_buf = buf_alloc();
3842 bigint_append_buf(val_buf, &const_val->data.x_bigint, 10);
3843 ir_add_error_node(ira, instruction->source_node,
3844 buf_sprintf("type %s cannot represent integer value %s",
3845 buf_ptr(&other_type->name),
3846 buf_ptr(val_buf)));
3847 return false;
3848 }
3849 if (other_type->data.floating.bit_count >= const_val->type->data.floating.bit_count) {
3850 return true;
3851 }
3852 switch (other_type->data.floating.bit_count) {
3853 case 16:
3854 switch (const_val->type->data.floating.bit_count) {
3855 case 32: {
3856 float16_t tmp = zig_double_to_f16(const_val->data.x_f32);
3857 float orig = zig_f16_to_double(tmp);
3858 if (const_val->data.x_f32 == orig) {
3859 return true;
3860 }
3861 break;
3862 }
3863 case 64: {
3864 float16_t tmp = zig_double_to_f16(const_val->data.x_f64);
3865 double orig = zig_f16_to_double(tmp);
3866 if (const_val->data.x_f64 == orig) {
3867 return true;
3868 }
3869 break;
3870 }
3871 case 80: {
3872 float16_t tmp = extF80M_to_f16(&const_val->data.x_f80);
3873 extFloat80_t orig;
3874 f16_to_extF80M(tmp, &orig);
3875 if (extF80M_eq(&orig, &const_val->data.x_f80)) {
3876 return true;
3877 }
3878 break;
3879 }
3880 case 128: {
3881 float16_t tmp = f128M_to_f16(&const_val->data.x_f128);
3882 float128_t orig;
3883 f16_to_f128M(tmp, &orig);
3884 if (f128M_eq(&orig, &const_val->data.x_f128)) {
3885 return true;
3886 }
3887 break;
3888 }
3889 default:
3890 zig_unreachable();
3891 }
3892 break;
3893 case 32:
3894 switch (const_val->type->data.floating.bit_count) {
3895 case 64: {
3896 float tmp = const_val->data.x_f64;
3897 double orig = tmp;
3898 if (const_val->data.x_f64 == orig) {
3899 return true;
3900 }
3901 break;
3902 }
3903 case 80: {
3904 float32_t tmp = extF80M_to_f32(&const_val->data.x_f80);
3905 extFloat80_t orig;
3906 f32_to_extF80M(tmp, &orig);
3907 if (extF80M_eq(&orig, &const_val->data.x_f80)) {
3908 return true;
3909 }
3910 break;
3911 }
3912 case 128: {
3913 float32_t tmp = f128M_to_f32(&const_val->data.x_f128);
3914 float128_t orig;
3915 f32_to_f128M(tmp, &orig);
3916 if (f128M_eq(&orig, &const_val->data.x_f128)) {
3917 return true;
3918 }
3919 break;
3920 }
3921 default:
3922 zig_unreachable();
3923 }
3924 break;
3925 case 64:
3926 switch (const_val->type->data.floating.bit_count) {
3927 case 80: {
3928 float64_t tmp = extF80M_to_f64(&const_val->data.x_f80);
3929 extFloat80_t orig;
3930 f64_to_extF80M(tmp, &orig);
3931 if (extF80M_eq(&orig, &const_val->data.x_f80)) {
3932 return true;
3933 }
3934 break;
3935 }
3936 case 128: {
3937 float64_t tmp = f128M_to_f64(&const_val->data.x_f128);
3938 float128_t orig;
3939 f64_to_f128M(tmp, &orig);
3940 if (f128M_eq(&orig, &const_val->data.x_f128)) {
3941 return true;
3942 }
3943 break;
3944 }
3945 default:
3946 zig_unreachable();
3947 }
3948 break;
3949 case 80: {
3950 assert(const_val->type->data.floating.bit_count == 128);
3951 extFloat80_t tmp;
3952 f128M_to_extF80M(&const_val->data.x_f128, &tmp);
3953 float128_t orig;
3954 extF80M_to_f128M(&tmp, &orig);
3955 if (f128M_eq(&orig, &const_val->data.x_f128)) {
3956 return true;
3957 }
3958 break;
3959 }
3960 case 128:
3961 return true;
3962 default:
3963 zig_unreachable();
3964 }
3965 Buf *val_buf = buf_alloc();
3966 float_append_buf(val_buf, const_val);
3967 ir_add_error_node(ira, instruction->source_node,
3968 buf_sprintf("cast of value %s to type '%s' loses information",
3969 buf_ptr(val_buf),
3970 buf_ptr(&other_type->name)));
3971 return false;
3972 } else if (other_type->id == ZigTypeIdInt && const_val_is_int) {
3973 if (!other_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) {
3974 Buf *val_buf = buf_alloc();
3975 bigint_append_buf(val_buf, &const_val->data.x_bigint, 10);
3976 ir_add_error_node(ira, instruction->source_node,
3977 buf_sprintf("cannot cast negative value %s to unsigned integer type '%s'",
3978 buf_ptr(val_buf),
3979 buf_ptr(&other_type->name)));
3980 return false;
3981 }
3982 if (bigint_fits_in_bits(&const_val->data.x_bigint, other_type->data.integral.bit_count,
3983 other_type->data.integral.is_signed))
3984 {
3985 return true;
3986 }
3987 } else if (const_val_fits_in_num_lit(const_val, other_type)) {
3988 return true;
3989 } else if (other_type->id == ZigTypeIdOptional) {
3990 ZigType *child_type = other_type->data.maybe.child_type;
3991 if (const_val_fits_in_num_lit(const_val, child_type)) {
3992 return true;
3993 } else if (child_type->id == ZigTypeIdInt && const_val_is_int) {
3994 if (!child_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) {
3995 Buf *val_buf = buf_alloc();
3996 bigint_append_buf(val_buf, &const_val->data.x_bigint, 10);
3997 ir_add_error_node(ira, instruction->source_node,
3998 buf_sprintf("cannot cast negative value %s to unsigned integer type '%s'",
3999 buf_ptr(val_buf),
4000 buf_ptr(&child_type->name)));
4001 return false;
4002 }
4003 if (bigint_fits_in_bits(&const_val->data.x_bigint,
4004 child_type->data.integral.bit_count,
4005 child_type->data.integral.is_signed))
4006 {
4007 return true;
4008 }
4009 } else if (child_type->id == ZigTypeIdFloat && const_val_is_float) {
4010 return true;
4011 }
4012 }
4013 if (explicit_cast && (other_type->id == ZigTypeIdInt || other_type->id == ZigTypeIdComptimeInt) &&
4014 const_val_is_float)
4015 {
4016 if (float_has_fraction(const_val)) {
4017 Buf *val_buf = buf_alloc();
4018 float_append_buf(val_buf, const_val);
4019
4020 ir_add_error_node(ira, instruction->source_node,
4021 buf_sprintf("fractional component prevents float value %s from being casted to type '%s'",
4022 buf_ptr(val_buf),
4023 buf_ptr(&other_type->name)));
4024 return false;
4025 } else {
4026 if (other_type->id == ZigTypeIdComptimeInt) {
4027 return true;
4028 } else {
4029 BigInt bigint;
4030 float_init_bigint(&bigint, const_val);
4031 if (bigint_fits_in_bits(&bigint, other_type->data.integral.bit_count,
4032 other_type->data.integral.is_signed))
4033 {
4034 return true;
4035 }
4036 }
4037 }
4038 }
4039
4040 const char *num_lit_str;
4041 Buf *val_buf = buf_alloc();
4042 if (const_val_is_float) {
4043 num_lit_str = "float";
4044 float_append_buf(val_buf, const_val);
4045 } else {
4046 num_lit_str = "integer";
4047 bigint_append_buf(val_buf, &const_val->data.x_bigint, 10);
4048 }
4049
4050 ir_add_error_node(ira, instruction->source_node,
4051 buf_sprintf("%s value %s cannot be coerced to type '%s'",
4052 num_lit_str,
4053 buf_ptr(val_buf),
4054 buf_ptr(&other_type->name)));
4055 return false;
4056}
4057
4058static bool is_tagged_union(ZigType *type) {
4059 if (type->id != ZigTypeIdUnion)
4060 return false;
4061 return (type->data.unionation.decl_node->data.container_decl.auto_enum ||
4062 type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr);
4063}
4064
4065static void populate_error_set_table(ErrorTableEntry **errors, ZigType *set) {
4066 assert(set->id == ZigTypeIdErrorSet);
4067 for (uint32_t i = 0; i < set->data.error_set.err_count; i += 1) {
4068 ErrorTableEntry *error_entry = set->data.error_set.errors[i];
4069 assert(errors[error_entry->value] == nullptr);
4070 errors[error_entry->value] = error_entry;
4071 }
4072}
4073
4074static ErrorTableEntry *better_documented_error(ErrorTableEntry *preferred, ErrorTableEntry *other) {
4075 if (preferred->decl_node->type == NodeTypeErrorSetField)
4076 return preferred;
4077 if (other->decl_node->type == NodeTypeErrorSetField)
4078 return other;
4079 return preferred;
4080}
4081
4082static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigType *set2,
4083 AstNode *source_node)
4084{
4085 assert(set1->id == ZigTypeIdErrorSet);
4086 assert(set2->id == ZigTypeIdErrorSet);
4087
4088 if (!resolve_inferred_error_set(ira->codegen, set1, source_node)) {
4089 return ira->codegen->builtin_types.entry_invalid;
4090 }
4091 if (!resolve_inferred_error_set(ira->codegen, set2, source_node)) {
4092 return ira->codegen->builtin_types.entry_invalid;
4093 }
4094 if (type_is_global_error_set(set1)) {
4095 return set2;
4096 }
4097 if (type_is_global_error_set(set2)) {
4098 return set1;
4099 }
4100 size_t errors_count = ira->codegen->errors_by_index.length;
4101 ErrorTableEntry **errors = heap::c_allocator.allocate<ErrorTableEntry *>(errors_count);
4102 populate_error_set_table(errors, set1);
4103 ZigList<ErrorTableEntry *> intersection_list = {};
4104
4105 ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
4106 buf_resize(&err_set_type->name, 0);
4107 buf_appendf(&err_set_type->name, "error{");
4108
4109 bool need_comma = false;
4110 for (uint32_t i = 0; i < set2->data.error_set.err_count; i += 1) {
4111 ErrorTableEntry *error_entry = set2->data.error_set.errors[i];
4112 ErrorTableEntry *existing_entry = errors[error_entry->value];
4113 if (existing_entry != nullptr) {
4114 // prefer the one with docs
4115 const char *comma = need_comma ? "," : "";
4116 need_comma = true;
4117 ErrorTableEntry *existing_entry_with_docs = better_documented_error(existing_entry, error_entry);
4118 intersection_list.append(existing_entry_with_docs);
4119 buf_appendf(&err_set_type->name, "%s%s", comma, buf_ptr(&existing_entry_with_docs->name));
4120 }
4121 }
4122 heap::c_allocator.deallocate(errors, errors_count);
4123
4124 err_set_type->data.error_set.err_count = intersection_list.length;
4125 err_set_type->data.error_set.errors = intersection_list.items;
4126 err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits;
4127 err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align;
4128 err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size;
4129
4130 buf_appendf(&err_set_type->name, "}");
4131
4132 return err_set_type;
4133}
4134
4135static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,
4136 ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)
4137{
4138 CodeGen *g = ira->codegen;
4139 ConstCastOnly result = {};
4140 result.id = ConstCastResultIdOk;
4141
4142 Error err;
4143
4144 if (wanted_type == actual_type)
4145 return result;
4146
4147 // If pointers have the same representation in memory, they can be "const-casted".
4148 // `const` attribute can be gained
4149 // `volatile` attribute can be gained
4150 // `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer)
4151 // but only if !wanted_is_mutable
4152 // alignment can be decreased
4153 // bit offset attributes must match exactly
4154 // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one
4155 // sentinel-terminated pointers can coerce into PtrLenUnknown
4156 ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
4157 ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
4158 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
4159 bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
4160 bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC;
4161 bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC;
4162 bool wanted_opt_or_ptr = wanted_ptr_type != nullptr && wanted_ptr_type->id == ZigTypeIdPointer;
4163 bool actual_opt_or_ptr = actual_ptr_type != nullptr && actual_ptr_type->id == ZigTypeIdPointer;
4164 if (wanted_opt_or_ptr && actual_opt_or_ptr) {
4165 bool ok_null_term_ptrs =
4166 wanted_ptr_type->data.pointer.sentinel == nullptr ||
4167 (actual_ptr_type->data.pointer.sentinel != nullptr &&
4168 const_values_equal(ira->codegen, wanted_ptr_type->data.pointer.sentinel,
4169 actual_ptr_type->data.pointer.sentinel)) ||
4170 actual_ptr_type->data.pointer.ptr_len == PtrLenC;
4171 if (!ok_null_term_ptrs) {
4172 result.id = ConstCastResultIdPtrSentinel;
4173 result.data.bad_ptr_sentinel = heap::c_allocator.allocate_nonzero<ConstCastPtrSentinel>(1);
4174 result.data.bad_ptr_sentinel->wanted_type = wanted_ptr_type;
4175 result.data.bad_ptr_sentinel->actual_type = actual_ptr_type;
4176 return result;
4177 }
4178 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
4179 if (!(ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr)) {
4180 result.id = ConstCastResultIdPtrLens;
4181 return result;
4182 }
4183
4184 bool ok_cv_qualifiers =
4185 (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
4186 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile);
4187 if (!ok_cv_qualifiers) {
4188 result.id = ConstCastResultIdCV;
4189 result.data.bad_cv = heap::c_allocator.allocate_nonzero<ConstCastBadCV>(1);
4190 result.data.bad_cv->wanted_type = wanted_ptr_type;
4191 result.data.bad_cv->actual_type = actual_ptr_type;
4192 return result;
4193 }
4194
4195 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
4196 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
4197 if (child.id == ConstCastResultIdInvalid)
4198 return child;
4199 if (child.id != ConstCastResultIdOk) {
4200 result.id = ConstCastResultIdPointerChild;
4201 result.data.pointer_mismatch = heap::c_allocator.allocate_nonzero<ConstCastPointerMismatch>(1);
4202 result.data.pointer_mismatch->child = child;
4203 result.data.pointer_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type;
4204 result.data.pointer_mismatch->actual_child = actual_ptr_type->data.pointer.child_type;
4205 return result;
4206 }
4207 bool ok_allows_zero = (wanted_allows_zero &&
4208 (actual_allows_zero || !wanted_is_mutable)) ||
4209 (!wanted_allows_zero && !actual_allows_zero);
4210 if (!ok_allows_zero) {
4211 result.id = ConstCastResultIdBadAllowsZero;
4212 result.data.bad_allows_zero = heap::c_allocator.allocate_nonzero<ConstCastBadAllowsZero>(1);
4213 result.data.bad_allows_zero->wanted_type = wanted_type;
4214 result.data.bad_allows_zero->actual_type = actual_type;
4215 return result;
4216 }
4217 if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
4218 result.id = ConstCastResultIdInvalid;
4219 return result;
4220 }
4221 if ((err = type_resolve(g, wanted_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
4222 result.id = ConstCastResultIdInvalid;
4223 return result;
4224 }
4225 if ((err = type_resolve(g, wanted_type, ResolveStatusZeroBitsKnown))) {
4226 result.id = ConstCastResultIdInvalid;
4227 return result;
4228 }
4229 if ((err = type_resolve(g, actual_type, ResolveStatusZeroBitsKnown))) {
4230 result.id = ConstCastResultIdInvalid;
4231 return result;
4232 }
4233 if (type_has_bits(g, wanted_type) == type_has_bits(g, actual_type) &&
4234 actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&
4235 actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes &&
4236 get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type))
4237 {
4238 return result;
4239 }
4240 }
4241
4242 // arrays
4243 if (wanted_type->id == ZigTypeIdArray && actual_type->id == ZigTypeIdArray &&
4244 wanted_type->data.array.len == actual_type->data.array.len)
4245 {
4246 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.array.child_type,
4247 actual_type->data.array.child_type, source_node, wanted_is_mutable);
4248 if (child.id == ConstCastResultIdInvalid)
4249 return child;
4250 if (child.id != ConstCastResultIdOk) {
4251 result.id = ConstCastResultIdArrayChild;
4252 result.data.array_mismatch = heap::c_allocator.allocate_nonzero<ConstCastArrayMismatch>(1);
4253 result.data.array_mismatch->child = child;
4254 result.data.array_mismatch->wanted_child = wanted_type->data.array.child_type;
4255 result.data.array_mismatch->actual_child = actual_type->data.array.child_type;
4256 return result;
4257 }
4258 bool ok_null_terminated = (wanted_type->data.array.sentinel == nullptr) ||
4259 (actual_type->data.array.sentinel != nullptr &&
4260 const_values_equal(ira->codegen, wanted_type->data.array.sentinel, actual_type->data.array.sentinel));
4261 if (!ok_null_terminated) {
4262 result.id = ConstCastResultIdSentinelArrays;
4263 result.data.sentinel_arrays = heap::c_allocator.allocate_nonzero<ConstCastBadNullTermArrays>(1);
4264 result.data.sentinel_arrays->child = child;
4265 result.data.sentinel_arrays->wanted_type = wanted_type;
4266 result.data.sentinel_arrays->actual_type = actual_type;
4267 return result;
4268 }
4269 return result;
4270 }
4271
4272 // slice const
4273 if (is_slice(wanted_type) && is_slice(actual_type)) {
4274 ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index]->type_entry;
4275 ZigType *wanted_ptr_type = wanted_type->data.structure.fields[slice_ptr_index]->type_entry;
4276 if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
4277 result.id = ConstCastResultIdInvalid;
4278 return result;
4279 }
4280 if ((err = type_resolve(g, wanted_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
4281 result.id = ConstCastResultIdInvalid;
4282 return result;
4283 }
4284 bool ok_sentinels =
4285 wanted_ptr_type->data.pointer.sentinel == nullptr ||
4286 (actual_ptr_type->data.pointer.sentinel != nullptr &&
4287 const_values_equal(ira->codegen, wanted_ptr_type->data.pointer.sentinel,
4288 actual_ptr_type->data.pointer.sentinel));
4289 if (!ok_sentinels) {
4290 result.id = ConstCastResultIdPtrSentinel;
4291 result.data.bad_ptr_sentinel = heap::c_allocator.allocate_nonzero<ConstCastPtrSentinel>(1);
4292 result.data.bad_ptr_sentinel->wanted_type = wanted_ptr_type;
4293 result.data.bad_ptr_sentinel->actual_type = actual_ptr_type;
4294 return result;
4295 }
4296 if ((!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
4297 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
4298 actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&
4299 actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes &&
4300 get_ptr_align(g, actual_ptr_type) >= get_ptr_align(g, wanted_ptr_type))
4301 {
4302 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
4303 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
4304 if (child.id == ConstCastResultIdInvalid)
4305 return child;
4306 if (child.id != ConstCastResultIdOk) {
4307 result.id = ConstCastResultIdSliceChild;
4308 result.data.slice_mismatch = heap::c_allocator.allocate_nonzero<ConstCastSliceMismatch>(1);
4309 result.data.slice_mismatch->child = child;
4310 result.data.slice_mismatch->actual_child = actual_ptr_type->data.pointer.child_type;
4311 result.data.slice_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type;
4312 }
4313 return result;
4314 }
4315 }
4316
4317 // optional types
4318 if (wanted_type->id == ZigTypeIdOptional && actual_type->id == ZigTypeIdOptional) {
4319 // Consider the case where the wanted type is ??[*]T and the actual one
4320 // is ?[*]T, we cannot turn the former into the latter even though the
4321 // child types are compatible (?[*]T and [*]T are both represented as a
4322 // pointer). The extra level of indirection in ??[*]T means it's
4323 // represented as a regular, fat, optional type and, as a consequence,
4324 // has a different shape than the one of ?[*]T.
4325 if ((wanted_ptr_type != nullptr) != (actual_ptr_type != nullptr)) {
4326 // The use of type_mismatch is intentional
4327 result.id = ConstCastResultIdOptionalShape;
4328 result.data.type_mismatch = heap::c_allocator.allocate_nonzero<ConstCastTypeMismatch>(1);
4329 result.data.type_mismatch->wanted_type = wanted_type;
4330 result.data.type_mismatch->actual_type = actual_type;
4331 return result;
4332 }
4333 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.maybe.child_type,
4334 actual_type->data.maybe.child_type, source_node, wanted_is_mutable);
4335 if (child.id == ConstCastResultIdInvalid)
4336 return child;
4337 if (child.id != ConstCastResultIdOk) {
4338 result.id = ConstCastResultIdOptionalChild;
4339 result.data.optional = heap::c_allocator.allocate_nonzero<ConstCastOptionalMismatch>(1);
4340 result.data.optional->child = child;
4341 result.data.optional->wanted_child = wanted_type->data.maybe.child_type;
4342 result.data.optional->actual_child = actual_type->data.maybe.child_type;
4343 }
4344 return result;
4345 }
4346
4347 // error union
4348 if (wanted_type->id == ZigTypeIdErrorUnion && actual_type->id == ZigTypeIdErrorUnion) {
4349 ConstCastOnly payload_child = types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type,
4350 actual_type->data.error_union.payload_type, source_node, wanted_is_mutable);
4351 if (payload_child.id == ConstCastResultIdInvalid)
4352 return payload_child;
4353 if (payload_child.id != ConstCastResultIdOk) {
4354 result.id = ConstCastResultIdErrorUnionPayload;
4355 result.data.error_union_payload = heap::c_allocator.allocate_nonzero<ConstCastErrUnionPayloadMismatch>(1);
4356 result.data.error_union_payload->child = payload_child;
4357 result.data.error_union_payload->wanted_payload = wanted_type->data.error_union.payload_type;
4358 result.data.error_union_payload->actual_payload = actual_type->data.error_union.payload_type;
4359 return result;
4360 }
4361 ConstCastOnly error_set_child = types_match_const_cast_only(ira, wanted_type->data.error_union.err_set_type,
4362 actual_type->data.error_union.err_set_type, source_node, wanted_is_mutable);
4363 if (error_set_child.id == ConstCastResultIdInvalid)
4364 return error_set_child;
4365 if (error_set_child.id != ConstCastResultIdOk) {
4366 result.id = ConstCastResultIdErrorUnionErrorSet;
4367 result.data.error_union_error_set = heap::c_allocator.allocate_nonzero<ConstCastErrUnionErrSetMismatch>(1);
4368 result.data.error_union_error_set->child = error_set_child;
4369 result.data.error_union_error_set->wanted_err_set = wanted_type->data.error_union.err_set_type;
4370 result.data.error_union_error_set->actual_err_set = actual_type->data.error_union.err_set_type;
4371 return result;
4372 }
4373 return result;
4374 }
4375
4376 // error set
4377 if (wanted_type->id == ZigTypeIdErrorSet && actual_type->id == ZigTypeIdErrorSet) {
4378 ZigType *contained_set = actual_type;
4379 ZigType *container_set = wanted_type;
4380
4381 // if the container set is inferred, then this will always work.
4382 if (container_set->data.error_set.infer_fn != nullptr && container_set->data.error_set.incomplete) {
4383 return result;
4384 }
4385 // if the container set is the global one, it will always work.
4386 if (type_is_global_error_set(container_set)) {
4387 return result;
4388 }
4389
4390 if (!resolve_inferred_error_set(ira->codegen, contained_set, source_node)) {
4391 result.id = ConstCastResultIdUnresolvedInferredErrSet;
4392 return result;
4393 }
4394
4395 if (type_is_global_error_set(contained_set)) {
4396 result.id = ConstCastResultIdErrSetGlobal;
4397 return result;
4398 }
4399
4400 size_t errors_count = g->errors_by_index.length;
4401 ErrorTableEntry **errors = heap::c_allocator.allocate<ErrorTableEntry *>(errors_count);
4402 for (uint32_t i = 0; i < container_set->data.error_set.err_count; i += 1) {
4403 ErrorTableEntry *error_entry = container_set->data.error_set.errors[i];
4404 assert(errors[error_entry->value] == nullptr);
4405 errors[error_entry->value] = error_entry;
4406 }
4407 for (uint32_t i = 0; i < contained_set->data.error_set.err_count; i += 1) {
4408 ErrorTableEntry *contained_error_entry = contained_set->data.error_set.errors[i];
4409 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
4410 if (error_entry == nullptr) {
4411 if (result.id == ConstCastResultIdOk) {
4412 result.id = ConstCastResultIdErrSet;
4413 result.data.error_set_mismatch = heap::c_allocator.create<ConstCastErrSetMismatch>();
4414 }
4415 result.data.error_set_mismatch->missing_errors.append(contained_error_entry);
4416 }
4417 }
4418 heap::c_allocator.deallocate(errors, errors_count);
4419 return result;
4420 }
4421
4422 // fn
4423 if (wanted_type->id == ZigTypeIdFn &&
4424 actual_type->id == ZigTypeIdFn)
4425 {
4426 if (wanted_type->data.fn.fn_type_id.alignment > actual_type->data.fn.fn_type_id.alignment) {
4427 result.id = ConstCastResultIdFnAlign;
4428 return result;
4429 }
4430 if (wanted_type->data.fn.fn_type_id.is_var_args != actual_type->data.fn.fn_type_id.is_var_args) {
4431 result.id = ConstCastResultIdFnVarArgs;
4432 return result;
4433 }
4434 if (wanted_type->data.fn.is_generic != actual_type->data.fn.is_generic) {
4435 result.id = ConstCastResultIdFnIsGeneric;
4436 return result;
4437 }
4438 if (!wanted_type->data.fn.is_generic &&
4439 actual_type->data.fn.fn_type_id.return_type->id != ZigTypeIdUnreachable)
4440 {
4441 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.fn.fn_type_id.return_type,
4442 actual_type->data.fn.fn_type_id.return_type, source_node, false);
4443 if (child.id == ConstCastResultIdInvalid)
4444 return child;
4445 if (child.id != ConstCastResultIdOk) {
4446 result.id = ConstCastResultIdFnReturnType;
4447 result.data.return_type = heap::c_allocator.allocate_nonzero<ConstCastOnly>(1);
4448 *result.data.return_type = child;
4449 return result;
4450 }
4451 }
4452 if (wanted_type->data.fn.fn_type_id.param_count != actual_type->data.fn.fn_type_id.param_count) {
4453 result.id = ConstCastResultIdFnArgCount;
4454 return result;
4455 }
4456 if (wanted_type->data.fn.fn_type_id.next_param_index != actual_type->data.fn.fn_type_id.next_param_index) {
4457 result.id = ConstCastResultIdFnGenericArgCount;
4458 return result;
4459 }
4460 assert(wanted_type->data.fn.is_generic ||
4461 wanted_type->data.fn.fn_type_id.next_param_index == wanted_type->data.fn.fn_type_id.param_count);
4462 for (size_t i = 0; i < wanted_type->data.fn.fn_type_id.param_count; i += 1) {
4463 // note it's reversed for parameters
4464 FnTypeParamInfo *actual_param_info = &actual_type->data.fn.fn_type_id.param_info[i];
4465 FnTypeParamInfo *expected_param_info = &wanted_type->data.fn.fn_type_id.param_info[i];
4466
4467 ConstCastOnly arg_child = types_match_const_cast_only(ira, actual_param_info->type,
4468 expected_param_info->type, source_node, false);
4469 if (arg_child.id == ConstCastResultIdInvalid)
4470 return arg_child;
4471 if (arg_child.id != ConstCastResultIdOk) {
4472 result.id = ConstCastResultIdFnArg;
4473 result.data.fn_arg.arg_index = i;
4474 result.data.fn_arg.actual_param_type = actual_param_info->type;
4475 result.data.fn_arg.expected_param_type = expected_param_info->type;
4476 result.data.fn_arg.child = heap::c_allocator.allocate_nonzero<ConstCastOnly>(1);
4477 *result.data.fn_arg.child = arg_child;
4478 return result;
4479 }
4480
4481 if (expected_param_info->is_noalias != actual_param_info->is_noalias) {
4482 result.id = ConstCastResultIdFnArgNoAlias;
4483 result.data.arg_no_alias.arg_index = i;
4484 return result;
4485 }
4486 }
4487 if (wanted_type->data.fn.fn_type_id.cc != actual_type->data.fn.fn_type_id.cc) {
4488 // ConstCastResultIdFnCC is guaranteed to be the last one reported, meaning everything else is ok.
4489 result.id = ConstCastResultIdFnCC;
4490 return result;
4491 }
4492 return result;
4493 }
4494
4495 if (wanted_type->id == ZigTypeIdInt && actual_type->id == ZigTypeIdInt) {
4496 if (wanted_type->data.integral.is_signed != actual_type->data.integral.is_signed ||
4497 wanted_type->data.integral.bit_count != actual_type->data.integral.bit_count)
4498 {
4499 result.id = ConstCastResultIdIntShorten;
4500 result.data.int_shorten = heap::c_allocator.allocate_nonzero<ConstCastIntShorten>(1);
4501 result.data.int_shorten->wanted_type = wanted_type;
4502 result.data.int_shorten->actual_type = actual_type;
4503 return result;
4504 }
4505 return result;
4506 }
4507
4508 if (wanted_type->id == ZigTypeIdFloat && actual_type->id == ZigTypeIdFloat) {
4509 if (wanted_type->data.floating.bit_count == actual_type->data.floating.bit_count) {
4510 return result;
4511 }
4512 }
4513
4514 if (wanted_type->id == ZigTypeIdVector && actual_type->id == ZigTypeIdVector) {
4515 if (actual_type->data.vector.len != wanted_type->data.vector.len) {
4516 result.id = ConstCastResultIdVectorLength;
4517 return result;
4518 }
4519
4520 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.vector.elem_type,
4521 actual_type->data.vector.elem_type, source_node, false);
4522 if (child.id == ConstCastResultIdInvalid)
4523 return child;
4524 if (child.id != ConstCastResultIdOk) {
4525 result.id = ConstCastResultIdVectorChild;
4526 return result;
4527 }
4528
4529 return result;
4530 }
4531
4532 result.id = ConstCastResultIdType;
4533 result.data.type_mismatch = heap::c_allocator.allocate_nonzero<ConstCastTypeMismatch>(1);
4534 result.data.type_mismatch->wanted_type = wanted_type;
4535 result.data.type_mismatch->actual_type = actual_type;
4536 return result;
4537}
4538
4539static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *errors_count) {
4540 size_t old_errors_count = *errors_count;
4541 *errors_count = g->errors_by_index.length;
4542 *errors = heap::c_allocator.reallocate(*errors, old_errors_count, *errors_count);
4543}
4544
4545static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type,
4546 Stage1AirInst **instructions, size_t instruction_count)
4547{
4548 Error err;
4549 assert(instruction_count >= 1);
4550 Stage1AirInst *prev_inst;
4551 size_t i = 0;
4552 for (;;) {
4553 prev_inst = instructions[i];
4554 if (type_is_invalid(prev_inst->value->type)) {
4555 return ira->codegen->builtin_types.entry_invalid;
4556 }
4557 if (prev_inst->value->type->id == ZigTypeIdUnreachable) {
4558 i += 1;
4559 if (i == instruction_count) {
4560 return prev_inst->value->type;
4561 }
4562 continue;
4563 }
4564 break;
4565 }
4566 ErrorTableEntry **errors = nullptr;
4567 size_t errors_count = 0;
4568 ZigType *err_set_type = nullptr;
4569 if (prev_inst->value->type->id == ZigTypeIdErrorSet) {
4570 if (!resolve_inferred_error_set(ira->codegen, prev_inst->value->type, prev_inst->source_node)) {
4571 return ira->codegen->builtin_types.entry_invalid;
4572 }
4573 if (type_is_global_error_set(prev_inst->value->type)) {
4574 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
4575 } else {
4576 err_set_type = prev_inst->value->type;
4577 update_errors_helper(ira->codegen, &errors, &errors_count);
4578
4579 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
4580 ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i];
4581 assert(errors[error_entry->value] == nullptr);
4582 errors[error_entry->value] = error_entry;
4583 }
4584 }
4585 }
4586
4587 bool any_are_null = (prev_inst->value->type->id == ZigTypeIdNull);
4588 bool convert_to_const_slice = false;
4589 bool make_the_slice_const = false;
4590 bool make_the_pointer_const = false;
4591 for (; i < instruction_count; i += 1) {
4592 Stage1AirInst *cur_inst = instructions[i];
4593 ZigType *cur_type = cur_inst->value->type;
4594 ZigType *prev_type = prev_inst->value->type;
4595
4596 if (type_is_invalid(cur_type)) {
4597 return cur_type;
4598 }
4599
4600 if (prev_type == cur_type) {
4601 continue;
4602 }
4603
4604 if (prev_type->id == ZigTypeIdUnreachable) {
4605 prev_inst = cur_inst;
4606 continue;
4607 }
4608
4609 if (cur_type->id == ZigTypeIdUnreachable) {
4610 continue;
4611 }
4612
4613 if (prev_type->id == ZigTypeIdErrorSet) {
4614 ir_assert(err_set_type != nullptr, prev_inst);
4615 if (cur_type->id == ZigTypeIdErrorSet) {
4616 if (type_is_global_error_set(err_set_type)) {
4617 continue;
4618 }
4619 bool allow_infer = cur_type->data.error_set.infer_fn != nullptr &&
4620 cur_type->data.error_set.infer_fn == ira->fn;
4621 if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
4622 return ira->codegen->builtin_types.entry_invalid;
4623 }
4624 if (!allow_infer && type_is_global_error_set(cur_type)) {
4625 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
4626 prev_inst = cur_inst;
4627 continue;
4628 }
4629
4630 // number of declared errors might have increased now
4631 update_errors_helper(ira->codegen, &errors, &errors_count);
4632
4633 // if err_set_type is a superset of cur_type, keep err_set_type.
4634 // if cur_type is a superset of err_set_type, switch err_set_type to cur_type
4635 bool prev_is_superset = true;
4636 for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) {
4637 ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i];
4638 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
4639 if (error_entry == nullptr) {
4640 prev_is_superset = false;
4641 break;
4642 }
4643 }
4644 if (prev_is_superset) {
4645 continue;
4646 }
4647
4648 // unset everything in errors
4649 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
4650 ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i];
4651 errors[error_entry->value] = nullptr;
4652 }
4653 for (uint32_t i = 0, count = ira->codegen->errors_by_index.length; i < count; i += 1) {
4654 assert(errors[i] == nullptr);
4655 }
4656 for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) {
4657 ErrorTableEntry *error_entry = cur_type->data.error_set.errors[i];
4658 assert(errors[error_entry->value] == nullptr);
4659 errors[error_entry->value] = error_entry;
4660 }
4661 bool cur_is_superset = true;
4662 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
4663 ErrorTableEntry *contained_error_entry = err_set_type->data.error_set.errors[i];
4664 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
4665 if (error_entry == nullptr) {
4666 cur_is_superset = false;
4667 break;
4668 }
4669 }
4670 if (cur_is_superset) {
4671 err_set_type = cur_type;
4672 prev_inst = cur_inst;
4673 assert(errors != nullptr);
4674 continue;
4675 }
4676
4677 // neither of them are supersets. so we invent a new error set type that is a union of both of them
4678 err_set_type = get_error_set_union(ira->codegen, errors, cur_type, err_set_type, nullptr);
4679 assert(errors != nullptr);
4680 continue;
4681 } else if (cur_type->id == ZigTypeIdErrorUnion) {
4682 if (type_is_global_error_set(err_set_type)) {
4683 prev_inst = cur_inst;
4684 continue;
4685 }
4686 ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type;
4687 bool allow_infer = cur_err_set_type->data.error_set.infer_fn != nullptr &&
4688 cur_err_set_type->data.error_set.infer_fn == ira->fn;
4689 if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->source_node)) {
4690 return ira->codegen->builtin_types.entry_invalid;
4691 }
4692 if (!allow_infer && type_is_global_error_set(cur_err_set_type)) {
4693 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
4694 prev_inst = cur_inst;
4695 continue;
4696 }
4697
4698 update_errors_helper(ira->codegen, &errors, &errors_count);
4699
4700 // test if err_set_type is a subset of cur_type's error set
4701 // unset everything in errors
4702 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
4703 ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i];
4704 errors[error_entry->value] = nullptr;
4705 }
4706 for (uint32_t i = 0, count = ira->codegen->errors_by_index.length; i < count; i += 1) {
4707 assert(errors[i] == nullptr);
4708 }
4709 for (uint32_t i = 0; i < cur_err_set_type->data.error_set.err_count; i += 1) {
4710 ErrorTableEntry *error_entry = cur_err_set_type->data.error_set.errors[i];
4711 assert(errors[error_entry->value] == nullptr);
4712 errors[error_entry->value] = error_entry;
4713 }
4714 bool cur_is_superset = true;
4715 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
4716 ErrorTableEntry *contained_error_entry = err_set_type->data.error_set.errors[i];
4717 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
4718 if (error_entry == nullptr) {
4719 cur_is_superset = false;
4720 break;
4721 }
4722 }
4723 if (cur_is_superset) {
4724 err_set_type = cur_err_set_type;
4725 prev_inst = cur_inst;
4726 assert(errors != nullptr);
4727 continue;
4728 }
4729
4730 // not a subset. invent new error set type, union of both of them
4731 err_set_type = get_error_set_union(ira->codegen, errors, cur_err_set_type, err_set_type, nullptr);
4732 prev_inst = cur_inst;
4733 assert(errors != nullptr);
4734 continue;
4735 } else {
4736 prev_inst = cur_inst;
4737 continue;
4738 }
4739 }
4740
4741 if (cur_type->id == ZigTypeIdErrorSet) {
4742 bool allow_infer = cur_type->data.error_set.infer_fn != nullptr &&
4743 cur_type->data.error_set.infer_fn == ira->fn;
4744 if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
4745 return ira->codegen->builtin_types.entry_invalid;
4746 }
4747 if (!allow_infer && type_is_global_error_set(cur_type)) {
4748 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
4749 continue;
4750 }
4751 if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) {
4752 continue;
4753 }
4754
4755 update_errors_helper(ira->codegen, &errors, &errors_count);
4756
4757 if (err_set_type == nullptr) {
4758 bool allow_infer = false;
4759 if (prev_type->id == ZigTypeIdErrorUnion) {
4760 err_set_type = prev_type->data.error_union.err_set_type;
4761 allow_infer = err_set_type->data.error_set.infer_fn != nullptr &&
4762 err_set_type->data.error_set.infer_fn == ira->fn;
4763 } else {
4764 err_set_type = cur_type;
4765 }
4766
4767 if (!allow_infer && !resolve_inferred_error_set(ira->codegen, err_set_type, cur_inst->source_node)) {
4768 return ira->codegen->builtin_types.entry_invalid;
4769 }
4770
4771 if (!allow_infer && type_is_global_error_set(err_set_type)) {
4772 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
4773 continue;
4774 }
4775
4776 update_errors_helper(ira->codegen, &errors, &errors_count);
4777
4778 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
4779 ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i];
4780 assert(errors[error_entry->value] == nullptr);
4781 errors[error_entry->value] = error_entry;
4782 }
4783 if (err_set_type == cur_type) {
4784 continue;
4785 }
4786 }
4787 // check if the cur type error set is a subset
4788 bool prev_is_superset = true;
4789 for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) {
4790 ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i];
4791 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
4792 if (error_entry == nullptr) {
4793 prev_is_superset = false;
4794 break;
4795 }
4796 }
4797 if (prev_is_superset) {
4798 continue;
4799 }
4800 // not a subset. invent new error set type, union of both of them
4801 err_set_type = get_error_set_union(ira->codegen, errors, err_set_type, cur_type, nullptr);
4802 assert(errors != nullptr);
4803 continue;
4804 }
4805
4806 if (prev_type->id == ZigTypeIdErrorUnion && cur_type->id == ZigTypeIdErrorUnion) {
4807 ZigType *prev_payload_type = prev_type->data.error_union.payload_type;
4808 ZigType *cur_payload_type = cur_type->data.error_union.payload_type;
4809
4810 bool const_cast_prev = types_match_const_cast_only(ira, prev_payload_type, cur_payload_type,
4811 source_node, false).id == ConstCastResultIdOk;
4812 bool const_cast_cur = types_match_const_cast_only(ira, cur_payload_type, prev_payload_type,
4813 source_node, false).id == ConstCastResultIdOk;
4814
4815 if (const_cast_prev || const_cast_cur) {
4816 if (const_cast_cur) {
4817 prev_inst = cur_inst;
4818 }
4819
4820 ZigType *prev_err_set_type = (err_set_type == nullptr) ? prev_type->data.error_union.err_set_type : err_set_type;
4821 ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type;
4822 if (prev_err_set_type == cur_err_set_type)
4823 continue;
4824
4825 bool allow_infer_prev = prev_err_set_type->data.error_set.infer_fn != nullptr &&
4826 prev_err_set_type->data.error_set.infer_fn == ira->fn;
4827 bool allow_infer_cur = cur_err_set_type->data.error_set.infer_fn != nullptr &&
4828 cur_err_set_type->data.error_set.infer_fn == ira->fn;
4829
4830 if (!allow_infer_prev && !resolve_inferred_error_set(ira->codegen, prev_err_set_type, cur_inst->source_node)) {
4831 return ira->codegen->builtin_types.entry_invalid;
4832 }
4833
4834 if (!allow_infer_cur && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->source_node)) {
4835 return ira->codegen->builtin_types.entry_invalid;
4836 }
4837
4838 if ((!allow_infer_prev && type_is_global_error_set(prev_err_set_type)) ||
4839 (!allow_infer_cur && type_is_global_error_set(cur_err_set_type)))
4840 {
4841 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
4842 continue;
4843 }
4844
4845 update_errors_helper(ira->codegen, &errors, &errors_count);
4846
4847 if (err_set_type == nullptr) {
4848 err_set_type = prev_err_set_type;
4849 for (uint32_t i = 0; i < prev_err_set_type->data.error_set.err_count; i += 1) {
4850 ErrorTableEntry *error_entry = prev_err_set_type->data.error_set.errors[i];
4851 assert(errors[error_entry->value] == nullptr);
4852 errors[error_entry->value] = error_entry;
4853 }
4854 }
4855 bool prev_is_superset = true;
4856 for (uint32_t i = 0; i < cur_err_set_type->data.error_set.err_count; i += 1) {
4857 ErrorTableEntry *contained_error_entry = cur_err_set_type->data.error_set.errors[i];
4858 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
4859 if (error_entry == nullptr) {
4860 prev_is_superset = false;
4861 break;
4862 }
4863 }
4864 if (prev_is_superset) {
4865 continue;
4866 }
4867 // unset all the errors
4868 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
4869 ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i];
4870 errors[error_entry->value] = nullptr;
4871 }
4872 for (uint32_t i = 0, count = ira->codegen->errors_by_index.length; i < count; i += 1) {
4873 assert(errors[i] == nullptr);
4874 }
4875 for (uint32_t i = 0; i < cur_err_set_type->data.error_set.err_count; i += 1) {
4876 ErrorTableEntry *error_entry = cur_err_set_type->data.error_set.errors[i];
4877 assert(errors[error_entry->value] == nullptr);
4878 errors[error_entry->value] = error_entry;
4879 }
4880 bool cur_is_superset = true;
4881 for (uint32_t i = 0; i < prev_err_set_type->data.error_set.err_count; i += 1) {
4882 ErrorTableEntry *contained_error_entry = prev_err_set_type->data.error_set.errors[i];
4883 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
4884 if (error_entry == nullptr) {
4885 cur_is_superset = false;
4886 break;
4887 }
4888 }
4889 if (cur_is_superset) {
4890 err_set_type = cur_err_set_type;
4891 continue;
4892 }
4893
4894 err_set_type = get_error_set_union(ira->codegen, errors, cur_err_set_type, prev_err_set_type, nullptr);
4895 continue;
4896 }
4897 }
4898
4899 if (prev_type->id == ZigTypeIdNull) {
4900 prev_inst = cur_inst;
4901 any_are_null = true;
4902 continue;
4903 }
4904
4905 if (cur_type->id == ZigTypeIdNull) {
4906 any_are_null = true;
4907 continue;
4908 }
4909
4910 if (prev_type->id == ZigTypeIdEnum && cur_type->id == ZigTypeIdEnumLiteral) {
4911 TypeEnumField *field = find_enum_type_field(prev_type, cur_inst->value->data.x_enum_literal);
4912 if (field != nullptr) {
4913 continue;
4914 }
4915 }
4916 if (is_tagged_union(prev_type) && cur_type->id == ZigTypeIdEnumLiteral) {
4917 TypeUnionField *field = find_union_type_field(prev_type, cur_inst->value->data.x_enum_literal);
4918 if (field != nullptr) {
4919 continue;
4920 }
4921 }
4922
4923 if (cur_type->id == ZigTypeIdEnum && prev_type->id == ZigTypeIdEnumLiteral) {
4924 TypeEnumField *field = find_enum_type_field(cur_type, prev_inst->value->data.x_enum_literal);
4925 if (field != nullptr) {
4926 prev_inst = cur_inst;
4927 continue;
4928 }
4929 }
4930
4931 if (is_tagged_union(cur_type) && prev_type->id == ZigTypeIdEnumLiteral) {
4932 TypeUnionField *field = find_union_type_field(cur_type, prev_inst->value->data.x_enum_literal);
4933 if (field != nullptr) {
4934 prev_inst = cur_inst;
4935 continue;
4936 }
4937 }
4938
4939 if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenC &&
4940 (cur_type->id == ZigTypeIdComptimeInt || cur_type->id == ZigTypeIdInt))
4941 {
4942 continue;
4943 }
4944
4945 if (cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenC &&
4946 (prev_type->id == ZigTypeIdComptimeInt || prev_type->id == ZigTypeIdInt))
4947 {
4948 prev_inst = cur_inst;
4949 continue;
4950 }
4951
4952 if (prev_type->id == ZigTypeIdPointer && cur_type->id == ZigTypeIdPointer) {
4953 if (prev_type->data.pointer.ptr_len == PtrLenC &&
4954 types_match_const_cast_only(ira, prev_type->data.pointer.child_type,
4955 cur_type->data.pointer.child_type, source_node,
4956 !prev_type->data.pointer.is_const).id == ConstCastResultIdOk)
4957 {
4958 continue;
4959 }
4960 if (cur_type->data.pointer.ptr_len == PtrLenC &&
4961 types_match_const_cast_only(ira, cur_type->data.pointer.child_type,
4962 prev_type->data.pointer.child_type, source_node,
4963 !cur_type->data.pointer.is_const).id == ConstCastResultIdOk)
4964 {
4965 prev_inst = cur_inst;
4966 continue;
4967 }
4968 }
4969
4970 if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) {
4971 continue;
4972 }
4973
4974 if (types_match_const_cast_only(ira, cur_type, prev_type, source_node, false).id == ConstCastResultIdOk) {
4975 prev_inst = cur_inst;
4976 continue;
4977 }
4978
4979 if (prev_type->id == ZigTypeIdInt &&
4980 cur_type->id == ZigTypeIdInt)
4981 {
4982 if ((prev_type->data.integral.is_signed == cur_type->data.integral.is_signed) ||
4983 (cur_type->data.integral.is_signed && !prev_type->data.integral.is_signed)) {
4984 if (cur_type->data.integral.bit_count > prev_type->data.integral.bit_count) {
4985 prev_inst = cur_inst;
4986 }
4987 }
4988 continue;
4989 }
4990
4991 if (prev_type->id == ZigTypeIdFloat && cur_type->id == ZigTypeIdFloat) {
4992 if (cur_type->data.floating.bit_count > prev_type->data.floating.bit_count) {
4993 prev_inst = cur_inst;
4994 }
4995 continue;
4996 }
4997
4998 if (prev_type->id == ZigTypeIdErrorUnion &&
4999 types_match_const_cast_only(ira, prev_type->data.error_union.payload_type, cur_type,
5000 source_node, false).id == ConstCastResultIdOk)
5001 {
5002 continue;
5003 }
5004
5005 if (cur_type->id == ZigTypeIdErrorUnion &&
5006 types_match_const_cast_only(ira, cur_type->data.error_union.payload_type, prev_type,
5007 source_node, false).id == ConstCastResultIdOk)
5008 {
5009 if (err_set_type != nullptr) {
5010 ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type;
5011 bool allow_infer = cur_err_set_type->data.error_set.infer_fn != nullptr &&
5012 cur_err_set_type->data.error_set.infer_fn == ira->fn;
5013 if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->source_node)) {
5014 return ira->codegen->builtin_types.entry_invalid;
5015 }
5016 if ((!allow_infer && type_is_global_error_set(cur_err_set_type)) ||
5017 type_is_global_error_set(err_set_type))
5018 {
5019 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
5020 prev_inst = cur_inst;
5021 continue;
5022 }
5023
5024 update_errors_helper(ira->codegen, &errors, &errors_count);
5025
5026 err_set_type = get_error_set_union(ira->codegen, errors, err_set_type, cur_err_set_type, nullptr);
5027 }
5028 prev_inst = cur_inst;
5029 continue;
5030 }
5031
5032 if (prev_type->id == ZigTypeIdOptional &&
5033 types_match_const_cast_only(ira, prev_type->data.maybe.child_type, cur_type,
5034 source_node, false).id == ConstCastResultIdOk)
5035 {
5036 continue;
5037 }
5038
5039 if (cur_type->id == ZigTypeIdOptional &&
5040 types_match_const_cast_only(ira, cur_type->data.maybe.child_type, prev_type,
5041 source_node, false).id == ConstCastResultIdOk)
5042 {
5043 prev_inst = cur_inst;
5044 continue;
5045 }
5046
5047 if (prev_type->id == ZigTypeIdOptional &&
5048 types_match_const_cast_only(ira, cur_type, prev_type->data.maybe.child_type,
5049 source_node, false).id == ConstCastResultIdOk)
5050 {
5051 prev_inst = cur_inst;
5052 any_are_null = true;
5053 continue;
5054 }
5055
5056 if (cur_type->id == ZigTypeIdOptional &&
5057 types_match_const_cast_only(ira, prev_type, cur_type->data.maybe.child_type,
5058 source_node, false).id == ConstCastResultIdOk)
5059 {
5060 any_are_null = true;
5061 continue;
5062 }
5063
5064 if (cur_type->id == ZigTypeIdUndefined) {
5065 continue;
5066 }
5067
5068 if (prev_type->id == ZigTypeIdUndefined) {
5069 prev_inst = cur_inst;
5070 continue;
5071 }
5072
5073 if (prev_type->id == ZigTypeIdComptimeInt ||
5074 prev_type->id == ZigTypeIdComptimeFloat)
5075 {
5076 if (ir_num_lit_fits_in_other_type(ira, prev_inst, cur_type, false)) {
5077 prev_inst = cur_inst;
5078 continue;
5079 } else {
5080 return ira->codegen->builtin_types.entry_invalid;
5081 }
5082 }
5083
5084 if (cur_type->id == ZigTypeIdComptimeInt ||
5085 cur_type->id == ZigTypeIdComptimeFloat)
5086 {
5087 if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type, false)) {
5088 continue;
5089 } else {
5090 return ira->codegen->builtin_types.entry_invalid;
5091 }
5092 }
5093
5094 // *[N]T to [*]T
5095 if (prev_type->id == ZigTypeIdPointer &&
5096 prev_type->data.pointer.ptr_len == PtrLenSingle &&
5097 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
5098 ((cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenUnknown)))
5099 {
5100 convert_to_const_slice = false;
5101 prev_inst = cur_inst;
5102
5103 if (prev_type->data.pointer.is_const && !cur_type->data.pointer.is_const) {
5104 // const array pointer and non-const unknown pointer
5105 make_the_pointer_const = true;
5106 }
5107 continue;
5108 }
5109
5110 // *[N]T to [*]T
5111 if (cur_type->id == ZigTypeIdPointer &&
5112 cur_type->data.pointer.ptr_len == PtrLenSingle &&
5113 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
5114 ((prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenUnknown)))
5115 {
5116 if (cur_type->data.pointer.is_const && !prev_type->data.pointer.is_const) {
5117 // const array pointer and non-const unknown pointer
5118 make_the_pointer_const = true;
5119 }
5120 continue;
5121 }
5122
5123 // *[N]T to []T
5124 // *[N]T to E![]T
5125 if (cur_type->id == ZigTypeIdPointer &&
5126 cur_type->data.pointer.ptr_len == PtrLenSingle &&
5127 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
5128 ((prev_type->id == ZigTypeIdErrorUnion && is_slice(prev_type->data.error_union.payload_type)) ||
5129 is_slice(prev_type)))
5130 {
5131 ZigType *array_type = cur_type->data.pointer.child_type;
5132 ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ?
5133 prev_type->data.error_union.payload_type : prev_type;
5134 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
5135 if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
5136 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
5137 {
5138 bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
5139 !cur_type->data.pointer.is_const);
5140 if (!const_ok) make_the_slice_const = true;
5141 convert_to_const_slice = false;
5142 continue;
5143 }
5144 }
5145
5146 // *[N]T to []T
5147 // *[N]T to E![]T
5148 if (prev_type->id == ZigTypeIdPointer &&
5149 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
5150 prev_type->data.pointer.ptr_len == PtrLenSingle &&
5151 ((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) ||
5152 (cur_type->id == ZigTypeIdOptional && is_slice(cur_type->data.maybe.child_type)) ||
5153 is_slice(cur_type)))
5154 {
5155 ZigType *array_type = prev_type->data.pointer.child_type;
5156 ZigType *slice_type;
5157 switch (cur_type->id) {
5158 case ZigTypeIdErrorUnion:
5159 slice_type = cur_type->data.error_union.payload_type;
5160 break;
5161 case ZigTypeIdOptional:
5162 slice_type = cur_type->data.maybe.child_type;
5163 break;
5164 default:
5165 slice_type = cur_type;
5166 break;
5167 }
5168 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
5169 if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
5170 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
5171 {
5172 bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
5173 !prev_type->data.pointer.is_const);
5174 if (!const_ok) make_the_slice_const = true;
5175 prev_inst = cur_inst;
5176 convert_to_const_slice = false;
5177 continue;
5178 }
5179 }
5180
5181 // *[N]T and *[M]T
5182 if (cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenSingle &&
5183 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
5184 prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenSingle &&
5185 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
5186 (
5187 prev_type->data.pointer.child_type->data.array.sentinel == nullptr ||
5188 (cur_type->data.pointer.child_type->data.array.sentinel != nullptr &&
5189 const_values_equal(ira->codegen, prev_type->data.pointer.child_type->data.array.sentinel,
5190 cur_type->data.pointer.child_type->data.array.sentinel))
5191 ) &&
5192 types_match_const_cast_only(ira,
5193 cur_type->data.pointer.child_type->data.array.child_type,
5194 prev_type->data.pointer.child_type->data.array.child_type,
5195 source_node, !cur_type->data.pointer.is_const).id == ConstCastResultIdOk)
5196 {
5197 bool const_ok = (cur_type->data.pointer.is_const || !prev_type->data.pointer.is_const ||
5198 prev_type->data.pointer.child_type->data.array.len == 0);
5199 if (!const_ok) make_the_slice_const = true;
5200 prev_inst = cur_inst;
5201 convert_to_const_slice = true;
5202 continue;
5203 }
5204 if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenSingle &&
5205 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
5206 cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenSingle &&
5207 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
5208 (
5209 cur_type->data.pointer.child_type->data.array.sentinel == nullptr ||
5210 (prev_type->data.pointer.child_type->data.array.sentinel != nullptr &&
5211 const_values_equal(ira->codegen, cur_type->data.pointer.child_type->data.array.sentinel,
5212 prev_type->data.pointer.child_type->data.array.sentinel))
5213 ) &&
5214 types_match_const_cast_only(ira,
5215 prev_type->data.pointer.child_type->data.array.child_type,
5216 cur_type->data.pointer.child_type->data.array.child_type,
5217 source_node, !prev_type->data.pointer.is_const).id == ConstCastResultIdOk)
5218 {
5219 bool const_ok = (prev_type->data.pointer.is_const || !cur_type->data.pointer.is_const ||
5220 cur_type->data.pointer.child_type->data.array.len == 0);
5221 if (!const_ok) make_the_slice_const = true;
5222 convert_to_const_slice = true;
5223 continue;
5224 }
5225
5226 if (prev_type->id == ZigTypeIdEnum && is_tagged_union(cur_type)) {
5227 if ((err = type_resolve(ira->codegen, cur_type, ResolveStatusZeroBitsKnown)))
5228 return ira->codegen->builtin_types.entry_invalid;
5229 if (cur_type->data.unionation.tag_type == prev_type) {
5230 continue;
5231 }
5232 }
5233
5234 if (cur_type->id == ZigTypeIdEnum && is_tagged_union(prev_type)) {
5235 if ((err = type_resolve(ira->codegen, prev_type, ResolveStatusZeroBitsKnown)))
5236 return ira->codegen->builtin_types.entry_invalid;
5237 if (prev_type->data.unionation.tag_type == cur_type) {
5238 prev_inst = cur_inst;
5239 continue;
5240 }
5241 }
5242
5243 ErrorMsg *msg = ir_add_error_node(ira, source_node,
5244 buf_sprintf("incompatible types: '%s' and '%s'",
5245 buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));
5246 add_error_note(ira->codegen, msg, prev_inst->source_node,
5247 buf_sprintf("type '%s' here", buf_ptr(&prev_type->name)));
5248 add_error_note(ira->codegen, msg, cur_inst->source_node,
5249 buf_sprintf("type '%s' here", buf_ptr(&cur_type->name)));
5250
5251 return ira->codegen->builtin_types.entry_invalid;
5252 }
5253
5254 heap::c_allocator.deallocate(errors, errors_count);
5255
5256 if (convert_to_const_slice) {
5257 if (prev_inst->value->type->id == ZigTypeIdPointer) {
5258 ZigType *array_type = prev_inst->value->type->data.pointer.child_type;
5259 src_assert(array_type->id == ZigTypeIdArray, source_node);
5260 ZigType *ptr_type = get_pointer_to_type_extra2(
5261 ira->codegen, array_type->data.array.child_type,
5262 prev_inst->value->type->data.pointer.is_const || make_the_slice_const, false,
5263 PtrLenUnknown,
5264 0, 0, 0, false,
5265 VECTOR_INDEX_NONE, nullptr, array_type->data.array.sentinel);
5266 ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);
5267 if (err_set_type != nullptr) {
5268 return get_error_union_type(ira->codegen, err_set_type, slice_type);
5269 } else {
5270 return slice_type;
5271 }
5272 } else {
5273 zig_unreachable();
5274 }
5275 } else if (err_set_type != nullptr) {
5276 if (prev_inst->value->type->id == ZigTypeIdErrorSet) {
5277 return err_set_type;
5278 } else if (prev_inst->value->type->id == ZigTypeIdErrorUnion) {
5279 ZigType *payload_type = prev_inst->value->type->data.error_union.payload_type;
5280 if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown)))
5281 return ira->codegen->builtin_types.entry_invalid;
5282 return get_error_union_type(ira->codegen, err_set_type, payload_type);
5283 } else if (expected_type != nullptr && expected_type->id == ZigTypeIdErrorUnion) {
5284 ZigType *payload_type = expected_type->data.error_union.payload_type;
5285 if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown)))
5286 return ira->codegen->builtin_types.entry_invalid;
5287 return get_error_union_type(ira->codegen, err_set_type, payload_type);
5288 } else {
5289 if (prev_inst->value->type->id == ZigTypeIdComptimeInt ||
5290 prev_inst->value->type->id == ZigTypeIdComptimeFloat)
5291 {
5292 ir_add_error_node(ira, source_node,
5293 buf_sprintf("unable to make error union out of number literal"));
5294 return ira->codegen->builtin_types.entry_invalid;
5295 } else if (prev_inst->value->type->id == ZigTypeIdNull) {
5296 ir_add_error_node(ira, source_node,
5297 buf_sprintf("unable to make error union out of null literal"));
5298 return ira->codegen->builtin_types.entry_invalid;
5299 } else {
5300 if ((err = type_resolve(ira->codegen, prev_inst->value->type, ResolveStatusSizeKnown)))
5301 return ira->codegen->builtin_types.entry_invalid;
5302 return get_error_union_type(ira->codegen, err_set_type, prev_inst->value->type);
5303 }
5304 }
5305 } else if (any_are_null && prev_inst->value->type->id != ZigTypeIdNull) {
5306 if (prev_inst->value->type->id == ZigTypeIdOptional) {
5307 return prev_inst->value->type;
5308 } else {
5309 if ((err = type_resolve(ira->codegen, prev_inst->value->type, ResolveStatusSizeKnown)))
5310 return ira->codegen->builtin_types.entry_invalid;
5311 return get_optional_type(ira->codegen, prev_inst->value->type);
5312 }
5313 } else if (make_the_slice_const) {
5314 ZigType *slice_type;
5315 if (prev_inst->value->type->id == ZigTypeIdErrorUnion) {
5316 slice_type = prev_inst->value->type->data.error_union.payload_type;
5317 } else if (is_slice(prev_inst->value->type)) {
5318 slice_type = prev_inst->value->type;
5319 } else {
5320 zig_unreachable();
5321 }
5322 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
5323 ZigType *adjusted_ptr_type = adjust_ptr_const(ira->codegen, slice_ptr_type, make_the_slice_const);
5324 ZigType *adjusted_slice_type = get_slice_type(ira->codegen, adjusted_ptr_type);
5325 if (prev_inst->value->type->id == ZigTypeIdErrorUnion) {
5326 return get_error_union_type(ira->codegen, prev_inst->value->type->data.error_union.err_set_type,
5327 adjusted_slice_type);
5328 } else if (is_slice(prev_inst->value->type)) {
5329 return adjusted_slice_type;
5330 } else {
5331 zig_unreachable();
5332 }
5333 } else if (make_the_pointer_const) {
5334 return adjust_ptr_const(ira->codegen, prev_inst->value->type, make_the_pointer_const);
5335 } else {
5336 return prev_inst->value->type;
5337 }
5338}
5339
5340static bool eval_const_expr_implicit_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node,
5341 CastOp cast_op,
5342 ZigValue *other_val, ZigType *other_type,
5343 ZigValue *const_val, ZigType *new_type)
5344{
5345 const_val->special = other_val->special;
5346
5347 assert(other_val != const_val);
5348 switch (cast_op) {
5349 case CastOpNoCast:
5350 zig_unreachable();
5351 case CastOpErrSet:
5352 case CastOpBitCast:
5353 zig_panic("TODO: eval_const_expr_implicit_cast CastOpErrSet, CastOpBitCast");
5354 case CastOpNoop: {
5355 copy_const_val(ira->codegen, const_val, other_val);
5356 const_val->type = new_type;
5357 break;
5358 }
5359 case CastOpNumLitToConcrete:
5360 if (other_val->type->id == ZigTypeIdComptimeFloat) {
5361 assert(new_type->id == ZigTypeIdFloat);
5362 switch (new_type->data.floating.bit_count) {
5363 case 16:
5364 const_val->data.x_f16 = bigfloat_to_f16(&other_val->data.x_bigfloat);
5365 break;
5366 case 32:
5367 const_val->data.x_f32 = bigfloat_to_f32(&other_val->data.x_bigfloat);
5368 break;
5369 case 64:
5370 const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat);
5371 break;
5372 case 80: {
5373 float128_t tmp = bigfloat_to_f128(&other_val->data.x_bigfloat);
5374 f128M_to_extF80M(&tmp, &const_val->data.x_f80);
5375 break;
5376 }
5377 case 128:
5378 const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat);
5379 break;
5380 default:
5381 zig_unreachable();
5382 }
5383 } else if (other_val->type->id == ZigTypeIdComptimeInt) {
5384 bigint_init_bigint(&const_val->data.x_bigint, &other_val->data.x_bigint);
5385 } else {
5386 zig_unreachable();
5387 }
5388 const_val->type = new_type;
5389 break;
5390 case CastOpIntToFloat:
5391 if (new_type->id == ZigTypeIdFloat) {
5392 BigFloat bigfloat;
5393 bigfloat_init_bigint(&bigfloat, &other_val->data.x_bigint);
5394 switch (new_type->data.floating.bit_count) {
5395 case 16:
5396 const_val->data.x_f16 = bigfloat_to_f16(&bigfloat);
5397 break;
5398 case 32:
5399 const_val->data.x_f32 = bigfloat_to_f32(&bigfloat);
5400 break;
5401 case 64:
5402 const_val->data.x_f64 = bigfloat_to_f64(&bigfloat);
5403 break;
5404 case 80: {
5405 float128_t tmp = bigfloat_to_f128(&other_val->data.x_bigfloat);
5406 f128M_to_extF80M(&tmp, &const_val->data.x_f80);
5407 break;
5408 }
5409 case 128:
5410 const_val->data.x_f128 = bigfloat_to_f128(&bigfloat);
5411 break;
5412 default:
5413 zig_unreachable();
5414 }
5415 } else if (new_type->id == ZigTypeIdComptimeFloat) {
5416 bigfloat_init_bigint(&const_val->data.x_bigfloat, &other_val->data.x_bigint);
5417 } else {
5418 zig_unreachable();
5419 }
5420 const_val->special = ConstValSpecialStatic;
5421 break;
5422 case CastOpFloatToInt:
5423 float_init_bigint(&const_val->data.x_bigint, other_val);
5424 if (new_type->id == ZigTypeIdInt) {
5425 if (!bigint_fits_in_bits(&const_val->data.x_bigint, new_type->data.integral.bit_count,
5426 new_type->data.integral.is_signed))
5427 {
5428 Buf *int_buf = buf_alloc();
5429 bigint_append_buf(int_buf, &const_val->data.x_bigint, 10);
5430
5431 ir_add_error_node(ira, source_node,
5432 buf_sprintf("integer value '%s' cannot be stored in type '%s'",
5433 buf_ptr(int_buf), buf_ptr(&new_type->name)));
5434 return false;
5435 }
5436 }
5437
5438 const_val->special = ConstValSpecialStatic;
5439 break;
5440 case CastOpBoolToInt:
5441 bigint_init_unsigned(&const_val->data.x_bigint, other_val->data.x_bool ? 1 : 0);
5442 const_val->special = ConstValSpecialStatic;
5443 break;
5444 }
5445 return true;
5446}
5447
5448static Stage1AirInst *ir_const(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *ty) {
5449 Stage1AirInstConst *const_instruction = ir_create_inst_gen<Stage1AirInstConst>(&ira->new_irb,
5450 scope, source_node);
5451 Stage1AirInst *new_instruction = &const_instruction->base;
5452 new_instruction->value->type = ty;
5453 new_instruction->value->special = ConstValSpecialStatic;
5454 ira->new_irb.constants.append(&heap::c_allocator, const_instruction);
5455 return new_instruction;
5456}
5457
5458static Stage1AirInst *ir_const_noval(IrAnalyze *ira, Scope *scope, AstNode *source_node) {
5459 Stage1AirInstConst *const_instruction = ir_create_inst_noval<Stage1AirInstConst>(&ira->new_irb,
5460 scope, source_node);
5461 ira->new_irb.constants.append(&heap::c_allocator, const_instruction);
5462 return &const_instruction->base;
5463}
5464
5465// This function initializes the new Stage1AirInst with the provided ZigValue,
5466// rather than creating a new one.
5467static Stage1AirInst *ir_const_move(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigValue *val) {
5468 Stage1AirInst *result = ir_const_noval(ira, scope, source_node);
5469 result->value = val;
5470 return result;
5471}
5472
5473static Stage1AirInst *ir_resolve_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value,
5474 ZigType *wanted_type, CastOp cast_op)
5475{
5476 if (instr_is_comptime(value) || !type_has_bits(ira->codegen, wanted_type)) {
5477 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
5478 ZigValue *val = ir_resolve_const(ira, value, UndefBad);
5479 if (val == nullptr)
5480 return ira->codegen->invalid_inst_gen;
5481
5482 if (!eval_const_expr_implicit_cast(ira, scope, source_node, cast_op, val, val->type,
5483 result->value, wanted_type))
5484 {
5485 return ira->codegen->invalid_inst_gen;
5486 }
5487 return result;
5488 } else {
5489 return ir_build_cast(ira, scope, source_node,
5490 wanted_type, value, cast_op);
5491 }
5492}
5493
5494static Stage1AirInst *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
5495 Scope *scope, AstNode *source_node, Stage1AirInst *value, ZigType *wanted_type)
5496{
5497 src_assert(value->value->type->id == ZigTypeIdPointer, source_node);
5498
5499 Error err;
5500
5501 if ((err = type_resolve(ira->codegen, value->value->type->data.pointer.child_type,
5502 ResolveStatusAlignmentKnown)))
5503 {
5504 return ira->codegen->invalid_inst_gen;
5505 }
5506
5507 wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value->type));
5508
5509 if (instr_is_comptime(value)) {
5510 ZigValue *val = ir_resolve_const(ira, value, UndefOk);
5511 if (val == nullptr)
5512 return ira->codegen->invalid_inst_gen;
5513 if (val->special == ConstValSpecialUndef)
5514 return ir_const_undef(ira, scope, source_node, wanted_type);
5515
5516 ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, val, source_node);
5517 if (pointee == nullptr)
5518 return ira->codegen->invalid_inst_gen;
5519 if (pointee->special != ConstValSpecialRuntime) {
5520 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
5521 result->value->data.x_ptr.special = ConstPtrSpecialBaseArray;
5522 result->value->data.x_ptr.mut = val->data.x_ptr.mut;
5523 result->value->data.x_ptr.data.base_array.array_val = pointee;
5524 result->value->data.x_ptr.data.base_array.elem_index = 0;
5525 return result;
5526 }
5527 }
5528
5529 return ir_build_cast(ira, scope, source_node,
5530 wanted_type, value, CastOpBitCast);
5531}
5532
5533static Stage1AirInst *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, Scope *scope, AstNode *source_node,
5534 Stage1AirInst *array_ptr, ZigType *wanted_type, ResultLoc *result_loc)
5535{
5536 Error err;
5537
5538 assert(array_ptr->value->type->id == ZigTypeIdPointer);
5539 assert(array_ptr->value->type->data.pointer.child_type->id == ZigTypeIdArray);
5540
5541 ZigType *array_type = array_ptr->value->type->data.pointer.child_type;
5542 size_t array_len = array_type->data.array.len;
5543
5544 // A zero-sized array can be casted regardless of the destination alignment, or
5545 // whether the pointer is undefined, and the result is always comptime known.
5546 // TODO However, this is exposing a result location bug that I failed to solve on the first try.
5547 // If you want to try to fix the bug, uncomment this block and get the tests passing.
5548 //if (array_len == 0 && array_type->data.array.sentinel == nullptr) {
5549 // ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>();
5550 // undef_array->special = ConstValSpecialUndef;
5551 // undef_array->type = array_type;
5552
5553 // Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
5554 // init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false, nullptr);
5555 // result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst;
5556 // result->value->type = wanted_type;
5557 // return result;
5558 //}
5559
5560 if ((err = type_resolve(ira->codegen, array_ptr->value->type, ResolveStatusAlignmentKnown))) {
5561 return ira->codegen->invalid_inst_gen;
5562 }
5563
5564 if (array_len != 0) {
5565 wanted_type = adjust_slice_align(ira->codegen, wanted_type,
5566 get_ptr_align(ira->codegen, array_ptr->value->type));
5567 }
5568
5569 if (instr_is_comptime(array_ptr)) {
5570 UndefAllowed undef_allowed = (array_len == 0) ? UndefOk : UndefBad;
5571 ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, undef_allowed);
5572 if (array_ptr_val == nullptr)
5573 return ira->codegen->invalid_inst_gen;
5574 src_assert(is_slice(wanted_type), source_node);
5575 if (array_ptr_val->special == ConstValSpecialUndef) {
5576 ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>();
5577 undef_array->special = ConstValSpecialUndef;
5578 undef_array->type = array_type;
5579
5580 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
5581 init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false, nullptr);
5582 result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst;
5583 result->value->type = wanted_type;
5584 return result;
5585 }
5586 bool wanted_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
5587 // Optimization to avoid creating unnecessary ZigValue in const_ptr_pointee
5588 if (array_ptr_val->data.x_ptr.special == ConstPtrSpecialSubArray) {
5589 ZigValue *array_val = array_ptr_val->data.x_ptr.data.base_array.array_val;
5590 if (array_val->special != ConstValSpecialRuntime) {
5591 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
5592 init_const_slice(ira->codegen, result->value, array_val,
5593 array_ptr_val->data.x_ptr.data.base_array.elem_index,
5594 array_type->data.array.len, wanted_const, nullptr);
5595 result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
5596 result->value->type = wanted_type;
5597 return result;
5598 }
5599 } else if (array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
5600 ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, array_ptr_val, source_node);
5601 if (pointee == nullptr)
5602 return ira->codegen->invalid_inst_gen;
5603 if (pointee->special != ConstValSpecialRuntime) {
5604 assert(array_ptr_val->type->id == ZigTypeIdPointer);
5605
5606 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
5607 init_const_slice(ira->codegen, result->value, pointee, 0, array_type->data.array.len, wanted_const, nullptr);
5608 result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
5609 result->value->type = wanted_type;
5610 return result;
5611 }
5612 }
5613 }
5614
5615 if (result_loc == nullptr) result_loc = no_result_loc();
5616 Stage1AirInst *result_loc_inst = ir_resolve_result(ira, ira->suspend_source_instr,
5617 result_loc, wanted_type, nullptr, true, true);
5618 if (type_is_invalid(result_loc_inst->value->type) ||
5619 result_loc_inst->value->type->id == ZigTypeIdUnreachable)
5620 {
5621 return result_loc_inst;
5622 }
5623 return ir_build_ptr_of_array_to_slice(ira, scope, source_node, wanted_type, array_ptr, result_loc_inst);
5624}
5625
5626static Stage1AirBasicBlock *ir_get_new_bb(IrAnalyze *ira, Stage1ZirBasicBlock *old_bb, Stage1ZirInst *ref_old_instruction) {
5627 assert(old_bb);
5628
5629 if (old_bb->child) {
5630 if (ref_old_instruction == nullptr || old_bb->child->ref_instruction != ref_old_instruction) {
5631 return old_bb->child;
5632 }
5633 }
5634
5635 Stage1AirBasicBlock *new_bb = ir_build_bb_from(ira, old_bb);
5636 new_bb->ref_instruction = ref_old_instruction;
5637
5638 return new_bb;
5639}
5640
5641static Stage1AirBasicBlock *ir_get_new_bb_runtime(IrAnalyze *ira, Stage1ZirBasicBlock *old_bb, Stage1ZirInst *ref_old_instruction) {
5642 assert(ref_old_instruction != nullptr);
5643 Stage1AirBasicBlock *new_bb = ir_get_new_bb(ira, old_bb, ref_old_instruction);
5644 if (new_bb->must_be_comptime_source_node != nullptr) {
5645 ErrorMsg *msg = ir_add_error_node(ira, ref_old_instruction->source_node,
5646 buf_sprintf("control flow attempts to use compile-time variable at runtime"));
5647 add_error_note(ira->codegen, msg, new_bb->must_be_comptime_source_node,
5648 buf_sprintf("compile-time variable assigned here"));
5649 return nullptr;
5650 }
5651 return new_bb;
5652}
5653
5654static void ir_start_bb(IrAnalyze *ira, Stage1ZirBasicBlock *old_bb, Stage1ZirBasicBlock *const_predecessor_bb) {
5655 src_assert(!old_bb->suspended,
5656 (old_bb->instruction_list.length != 0) ?
5657 old_bb->instruction_list.at(0)->source_node : nullptr);
5658 ira->instruction_index = 0;
5659 ira->zir_current_basic_block = old_bb;
5660 ira->const_predecessor_bb = const_predecessor_bb;
5661 ira->old_bb_index = old_bb->index;
5662}
5663
5664static Stage1AirInst *ira_suspend(IrAnalyze *ira, Stage1ZirInst *old_instruction, Stage1ZirBasicBlock *next_bb,
5665 IrSuspendPosition *suspend_pos)
5666{
5667 if (ira->codegen->verbose_ir) {
5668 fprintf(stderr, "suspend %s_%" PRIu32 " %s_%" PRIu32 " #%" PRIu32 " (%zu,%zu)\n",
5669 ira->zir_current_basic_block->name_hint,
5670 ira->zir_current_basic_block->debug_id,
5671 ira->zir->basic_block_list.at(ira->old_bb_index)->name_hint,
5672 ira->zir->basic_block_list.at(ira->old_bb_index)->debug_id,
5673 ira->zir_current_basic_block->instruction_list.at(ira->instruction_index)->debug_id,
5674 ira->old_bb_index, ira->instruction_index);
5675 }
5676 suspend_pos->basic_block_index = ira->old_bb_index;
5677 suspend_pos->instruction_index = ira->instruction_index;
5678
5679 ira->zir_current_basic_block->suspended = true;
5680
5681 // null next_bb means that the caller plans to call ira_resume before returning
5682 if (next_bb != nullptr) {
5683 ira->old_bb_index = next_bb->index;
5684 ira->zir_current_basic_block = ira->zir->basic_block_list.at(ira->old_bb_index);
5685 assert(ira->zir_current_basic_block == next_bb);
5686 ira->instruction_index = 0;
5687 ira->const_predecessor_bb = nullptr;
5688 next_bb->child = ir_get_new_bb_runtime(ira, next_bb, old_instruction);
5689 ira->new_irb.current_basic_block = next_bb->child;
5690 }
5691 return ira->codegen->unreach_instruction;
5692}
5693
5694static Stage1AirInst *ira_resume(IrAnalyze *ira) {
5695 IrSuspendPosition pos = ira->resume_stack.pop();
5696 if (ira->codegen->verbose_ir) {
5697 fprintf(stderr, "resume (%zu,%zu) ", pos.basic_block_index, pos.instruction_index);
5698 }
5699 ira->old_bb_index = pos.basic_block_index;
5700 ira->zir_current_basic_block = ira->zir->basic_block_list.at(ira->old_bb_index);
5701 assert(ira->zir_current_basic_block->in_resume_stack);
5702 ira->zir_current_basic_block->in_resume_stack = false;
5703 ira->zir_current_basic_block->suspended = false;
5704 ira->instruction_index = pos.instruction_index;
5705 assert(pos.instruction_index < ira->zir_current_basic_block->instruction_list.length);
5706 if (ira->codegen->verbose_ir) {
5707 fprintf(stderr, "%s_%" PRIu32 " #%" PRIu32 "\n", ira->zir_current_basic_block->name_hint,
5708 ira->zir_current_basic_block->debug_id,
5709 ira->zir_current_basic_block->instruction_list.at(pos.instruction_index)->debug_id);
5710 }
5711 ira->const_predecessor_bb = nullptr;
5712 ira->new_irb.current_basic_block = ira->zir_current_basic_block->child;
5713 assert(ira->new_irb.current_basic_block != nullptr);
5714 return ira->codegen->unreach_instruction;
5715}
5716
5717static void ir_start_next_bb(IrAnalyze *ira) {
5718 ira->old_bb_index += 1;
5719
5720 bool need_repeat = true;
5721 for (;;) {
5722 while (ira->old_bb_index < ira->zir->basic_block_list.length) {
5723 Stage1ZirBasicBlock *old_bb = ira->zir->basic_block_list.at(ira->old_bb_index);
5724 if (old_bb->child == nullptr && old_bb->suspend_instruction_ref == nullptr) {
5725 ira->old_bb_index += 1;
5726 continue;
5727 }
5728 // if it's already started, or
5729 // if it's a suspended block,
5730 // then skip it
5731 if (old_bb->suspended ||
5732 (old_bb->child != nullptr && old_bb->child->instruction_list.length != 0) ||
5733 (old_bb->child != nullptr && old_bb->child->already_appended))
5734 {
5735 ira->old_bb_index += 1;
5736 continue;
5737 }
5738
5739 // if there is a resume_stack, pop one from there rather than moving on.
5740 // the last item of the resume stack will be a basic block that will
5741 // move on to the next one below
5742 if (ira->resume_stack.length != 0) {
5743 ira_resume(ira);
5744 return;
5745 }
5746
5747 if (old_bb->child == nullptr) {
5748 old_bb->child = ir_get_new_bb_runtime(ira, old_bb, old_bb->suspend_instruction_ref);
5749 }
5750 ira->new_irb.current_basic_block = old_bb->child;
5751 ir_start_bb(ira, old_bb, nullptr);
5752 return;
5753 }
5754 if (!need_repeat) {
5755 if (ira->resume_stack.length != 0) {
5756 ira_resume(ira);
5757 }
5758 return;
5759 }
5760 need_repeat = false;
5761 ira->old_bb_index = 0;
5762 continue;
5763 }
5764}
5765
5766static void ir_finish_bb(IrAnalyze *ira) {
5767 if (!ira->new_irb.current_basic_block->already_appended) {
5768 ir_append_basic_block_gen(&ira->new_irb, ira->new_irb.current_basic_block);
5769 if (ira->codegen->verbose_ir) {
5770 fprintf(stderr, "append new bb %s_%" PRIu32 "\n", ira->new_irb.current_basic_block->name_hint,
5771 ira->new_irb.current_basic_block->debug_id);
5772 }
5773 }
5774 ir_start_next_bb(ira);
5775}
5776
5777static Stage1AirInst *ir_unreach_error(IrAnalyze *ira) {
5778 ira->old_bb_index = SIZE_MAX;
5779 if (ira->new_irb.exec->first_err_trace_msg == nullptr) {
5780 ira->new_irb.exec->first_err_trace_msg = ira->codegen->trace_err;
5781 }
5782 return ira->codegen->unreach_instruction;
5783}
5784
5785static bool ir_emit_backward_branch(IrAnalyze *ira, AstNode* source_node) {
5786 size_t *bbc = ira->backward_branch_count;
5787 size_t *quota = ira->backward_branch_quota;
5788
5789 // If we're already over quota, we've already given an error message for this.
5790 if (*bbc > *quota) {
5791 assert(ira->codegen->errors.length > 0);
5792 return false;
5793 }
5794
5795 *bbc += 1;
5796 if (*bbc > *quota) {
5797 ErrorMsg *msg = ir_add_error_node(ira, source_node,
5798 buf_sprintf("evaluation exceeded %" ZIG_PRI_usize " backwards branches", *quota));
5799 add_error_note(ira->codegen, msg, source_node,
5800 buf_sprintf("use @setEvalBranchQuota to raise branch limit from %" ZIG_PRI_usize, *quota));
5801 return false;
5802 }
5803 return true;
5804}
5805
5806static Stage1AirInst *ir_inline_bb(IrAnalyze *ira, AstNode* source_node, Stage1ZirBasicBlock *old_bb) {
5807 if (old_bb->debug_id <= ira->zir_current_basic_block->debug_id) {
5808 if (!ir_emit_backward_branch(ira, source_node))
5809 return ir_unreach_error(ira);
5810 }
5811
5812 old_bb->child = ira->zir_current_basic_block->child;
5813 ir_start_bb(ira, old_bb, ira->zir_current_basic_block);
5814 return ira->codegen->unreach_instruction;
5815}
5816
5817static Stage1AirInst *ir_finish_anal(IrAnalyze *ira, Stage1AirInst *instruction) {
5818 if (instruction->value->type->id == ZigTypeIdUnreachable)
5819 ir_finish_bb(ira);
5820 return instruction;
5821}
5822
5823static Stage1AirInst *ir_const_fn(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigFn *fn_entry) {
5824 Stage1AirInst *result = ir_const(ira, scope, source_node, fn_entry->type_entry);
5825 result->value->special = ConstValSpecialStatic;
5826 result->value->data.x_ptr.data.fn.fn_entry = fn_entry;
5827 result->value->data.x_ptr.mut = ConstPtrMutComptimeConst;
5828 result->value->data.x_ptr.special = ConstPtrSpecialFunction;
5829 return result;
5830}
5831
5832static Stage1AirInst *ir_const_bound_fn(IrAnalyze *ira, Scope *scope, AstNode *source_node,
5833 ZigFn *fn_entry, Stage1AirInst *first_arg, AstNode *first_arg_src)
5834{
5835 // This is unfortunately required to avoid improperly freeing first_arg_src
5836 ira_ref(ira);
5837
5838 Stage1AirInst *result = ir_const(ira, scope, source_node, get_bound_fn_type(ira->codegen, fn_entry));
5839 result->value->data.x_bound_fn.fn = fn_entry;
5840 result->value->data.x_bound_fn.first_arg = first_arg;
5841 result->value->data.x_bound_fn.first_arg_src = first_arg_src;
5842 return result;
5843}
5844
5845static Stage1AirInst *ir_const_type(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *ty) {
5846 Stage1AirInst *result = ir_const(ira, scope, source_node, ira->codegen->builtin_types.entry_type);
5847 result->value->data.x_type = ty;
5848 return result;
5849}
5850
5851static Stage1AirInst *ir_const_bool(IrAnalyze *ira, Scope *scope, AstNode *source_node, bool value) {
5852 Stage1AirInst *result = ir_const(ira, scope, source_node, ira->codegen->builtin_types.entry_bool);
5853 result->value->data.x_bool = value;
5854 return result;
5855}
5856
5857static Stage1AirInst *ir_const_undef(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *ty) {
5858 Stage1AirInst *result = ir_const(ira, scope, source_node, ty);
5859 result->value->special = ConstValSpecialUndef;
5860 return result;
5861}
5862
5863static Stage1AirInst *ir_const_unreachable(IrAnalyze *ira, Scope *scope, AstNode *source_node) {
5864 Stage1AirInst *result = ir_const_noval(ira, scope, source_node);
5865 result->value = ira->codegen->intern.for_unreachable();
5866 return result;
5867}
5868
5869static Stage1AirInst *ir_const_void(IrAnalyze *ira, Scope *scope, AstNode *source_node) {
5870 Stage1AirInst *result = ir_const_noval(ira, scope, source_node);
5871 result->value = ira->codegen->intern.for_void();
5872 return result;
5873}
5874
5875static Stage1AirInst *ir_const_unsigned(IrAnalyze *ira, Scope *scope, AstNode *source_node, uint64_t value) {
5876 Stage1AirInst *result = ir_const(ira, scope, source_node, ira->codegen->builtin_types.entry_num_lit_int);
5877 bigint_init_unsigned(&result->value->data.x_bigint, value);
5878 return result;
5879}
5880
5881static Stage1AirInst *ir_get_const_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node,
5882 ZigValue *pointee, ZigType *pointee_type,
5883 ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile, uint32_t ptr_align)
5884{
5885 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, pointee_type,
5886 ptr_is_const, ptr_is_volatile, PtrLenSingle, ptr_align, 0, 0, false);
5887 Stage1AirInst *const_instr = ir_const(ira, scope, source_node, ptr_type);
5888 ZigValue *const_val = const_instr->value;
5889 const_val->data.x_ptr.special = ConstPtrSpecialRef;
5890 const_val->data.x_ptr.mut = ptr_mut;
5891 const_val->data.x_ptr.data.ref.pointee = pointee;
5892 return const_instr;
5893}
5894
5895static Error ir_resolve_const_val(CodeGen *codegen, Stage1Air *exec, AstNode *source_node,
5896 ZigValue *val, UndefAllowed undef_allowed)
5897{
5898 Error err;
5899 for (;;) {
5900 switch (val->special) {
5901 case ConstValSpecialStatic:
5902 return ErrorNone;
5903 case ConstValSpecialRuntime:
5904 if (!type_has_bits(codegen, val->type))
5905 return ErrorNone;
5906
5907 exec_add_error_node_gen(codegen, exec, source_node,
5908 buf_sprintf("unable to evaluate constant expression"));
5909 return ErrorSemanticAnalyzeFail;
5910 case ConstValSpecialUndef:
5911 if (undef_allowed == UndefOk || undef_allowed == LazyOk)
5912 return ErrorNone;
5913
5914 exec_add_error_node_gen(codegen, exec, source_node,
5915 buf_sprintf("use of undefined value here causes undefined behavior"));
5916 return ErrorSemanticAnalyzeFail;
5917 case ConstValSpecialLazy:
5918 if (undef_allowed == LazyOk || undef_allowed == LazyOkNoUndef)
5919 return ErrorNone;
5920
5921 if ((err = ir_resolve_lazy(codegen, source_node, val)))
5922 return err;
5923
5924 continue;
5925 }
5926 }
5927}
5928
5929static ZigValue *ir_resolve_const(IrAnalyze *ira, Stage1AirInst *value, UndefAllowed undef_allowed) {
5930 Error err;
5931 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, value->source_node,
5932 value->value, undef_allowed)))
5933 {
5934 return nullptr;
5935 }
5936 return value->value;
5937}
5938
5939Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
5940 ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota,
5941 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
5942 Stage1Air *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef_allowed)
5943{
5944 Error err;
5945
5946 src_assert(return_ptr->type->id == ZigTypeIdPointer, source_node);
5947
5948 if (type_is_invalid(return_ptr->type))
5949 return ErrorSemanticAnalyzeFail;
5950
5951 Stage1Zir *stage1_zir = heap::c_allocator.create<Stage1Zir>();
5952 stage1_zir->name = exec_name;
5953 stage1_zir->is_inline = true;
5954 stage1_zir->begin_scope = scope;
5955
5956 bool in_c_import_scope = c_import_buf != nullptr;
5957
5958 if (!stage1_astgen(codegen, node, scope, stage1_zir, fn_entry, in_c_import_scope))
5959 return ErrorSemanticAnalyzeFail;
5960
5961 if (stage1_zir->first_err_trace_msg != nullptr) {
5962 codegen->trace_err = stage1_zir->first_err_trace_msg;
5963 return ErrorSemanticAnalyzeFail;
5964 }
5965
5966 if (codegen->verbose_ir) {
5967 fprintf(stderr, "\n{ // (IR)\n");
5968 ir_print_src(codegen, stderr, stage1_zir, 2);
5969 fprintf(stderr, "}\n");
5970 }
5971 Stage1Air *analyzed_executable = heap::c_allocator.create<Stage1Air>();
5972 analyzed_executable->source_node = source_node;
5973 analyzed_executable->parent_exec = parent_exec;
5974 analyzed_executable->source_exec = stage1_zir;
5975 analyzed_executable->name = exec_name;
5976 analyzed_executable->is_inline = true;
5977 analyzed_executable->c_import_buf = c_import_buf;
5978 analyzed_executable->begin_scope = scope;
5979 ZigType *result_type = ir_analyze(codegen, stage1_zir, analyzed_executable,
5980 backward_branch_count, backward_branch_quota,
5981 return_ptr->type->data.pointer.child_type, expected_type_source_node, return_ptr,
5982 fn_entry);
5983 if (type_is_invalid(result_type)) {
5984 return ErrorSemanticAnalyzeFail;
5985 }
5986
5987 if (codegen->verbose_ir) {
5988 fprintf(stderr, "{ // (analyzed)\n");
5989 ir_print_gen(codegen, stderr, analyzed_executable, 2);
5990 fprintf(stderr, "}\n");
5991 }
5992
5993 if ((err = ir_exec_scan_for_side_effects(codegen, analyzed_executable)))
5994 return err;
5995
5996 ZigValue *result = const_ptr_pointee(nullptr, codegen, return_ptr, source_node);
5997 if (result == nullptr)
5998 return ErrorSemanticAnalyzeFail;
5999 if ((err = ir_resolve_const_val(codegen, analyzed_executable, node, result, undef_allowed)))
6000 return err;
6001
6002 return ErrorNone;
6003}
6004
6005static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, Stage1AirInst *err_value) {
6006 if (type_is_invalid(err_value->value->type))
6007 return nullptr;
6008
6009 if (err_value->value->type->id != ZigTypeIdErrorSet) {
6010 ir_add_error_node(ira, err_value->source_node,
6011 buf_sprintf("expected error, found '%s'", buf_ptr(&err_value->value->type->name)));
6012 return nullptr;
6013 }
6014
6015 ZigValue *const_val = ir_resolve_const(ira, err_value, UndefBad);
6016 if (!const_val)
6017 return nullptr;
6018
6019 assert(const_val->data.x_err_set != nullptr);
6020 return const_val->data.x_err_set;
6021}
6022
6023static ZigType *ir_resolve_const_type(CodeGen *codegen, Stage1Air *exec, AstNode *source_node,
6024 ZigValue *val)
6025{
6026 Error err;
6027 if ((err = ir_resolve_const_val(codegen, exec, source_node, val, UndefBad)))
6028 return codegen->builtin_types.entry_invalid;
6029
6030 assert(val->data.x_type != nullptr);
6031 return val->data.x_type;
6032}
6033
6034static ZigValue *ir_resolve_type_lazy(IrAnalyze *ira, Stage1AirInst *type_value) {
6035 if (type_is_invalid(type_value->value->type))
6036 return nullptr;
6037
6038 if (type_value->value->type->id != ZigTypeIdMetaType) {
6039 ir_add_error_node(ira, type_value->source_node,
6040 buf_sprintf("expected type 'type', found '%s'", buf_ptr(&type_value->value->type->name)));
6041 return nullptr;
6042 }
6043
6044 Error err;
6045 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, type_value->source_node,
6046 type_value->value, LazyOkNoUndef)))
6047 {
6048 return nullptr;
6049 }
6050
6051 return type_value->value;
6052}
6053
6054static ZigType *ir_resolve_type(IrAnalyze *ira, Stage1AirInst *type_value) {
6055 ZigValue *val = ir_resolve_type_lazy(ira, type_value);
6056 if (val == nullptr)
6057 return ira->codegen->builtin_types.entry_invalid;
6058
6059 return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, val);
6060}
6061
6062static Error ir_validate_vector_elem_type(IrAnalyze *ira, AstNode *source_node, ZigType *elem_type) {
6063 Error err;
6064 bool is_valid;
6065 if ((err = is_valid_vector_elem_type(ira->codegen, elem_type, &is_valid)))
6066 return err;
6067 if (!is_valid) {
6068 ir_add_error_node(ira, source_node,
6069 buf_sprintf("vector element type must be integer, float, bool, or pointer; '%s' is invalid",
6070 buf_ptr(&elem_type->name)));
6071 return ErrorSemanticAnalyzeFail;
6072 }
6073 return ErrorNone;
6074}
6075
6076static ZigType *ir_resolve_vector_elem_type(IrAnalyze *ira, Stage1AirInst *elem_type_value) {
6077 Error err;
6078 ZigType *elem_type = ir_resolve_type(ira, elem_type_value);
6079 if (type_is_invalid(elem_type))
6080 return ira->codegen->builtin_types.entry_invalid;
6081 if ((err = ir_validate_vector_elem_type(ira, elem_type_value->source_node, elem_type)))
6082 return ira->codegen->builtin_types.entry_invalid;
6083 return elem_type;
6084}
6085
6086static ZigType *ir_resolve_int_type(IrAnalyze *ira, Stage1AirInst *type_value) {
6087 ZigType *ty = ir_resolve_type(ira, type_value);
6088 if (type_is_invalid(ty))
6089 return ira->codegen->builtin_types.entry_invalid;
6090
6091 if (ty->id != ZigTypeIdInt) {
6092 ErrorMsg *msg = ir_add_error_node(ira, type_value->source_node,
6093 buf_sprintf("expected integer type, found '%s'", buf_ptr(&ty->name)));
6094 if (ty->id == ZigTypeIdVector &&
6095 ty->data.vector.elem_type->id == ZigTypeIdInt)
6096 {
6097 add_error_note(ira->codegen, msg, type_value->source_node,
6098 buf_sprintf("represent vectors with their element types, i.e. '%s'",
6099 buf_ptr(&ty->data.vector.elem_type->name)));
6100 }
6101 return ira->codegen->builtin_types.entry_invalid;
6102 }
6103
6104 return ty;
6105}
6106
6107static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, AstNode *op_source, Stage1AirInst *type_value) {
6108 if (type_is_invalid(type_value->value->type))
6109 return ira->codegen->builtin_types.entry_invalid;
6110
6111 if (type_value->value->type->id != ZigTypeIdMetaType) {
6112 ErrorMsg *msg = ir_add_error_node(ira, type_value->source_node,
6113 buf_sprintf("expected error set type, found '%s'", buf_ptr(&type_value->value->type->name)));
6114 add_error_note(ira->codegen, msg, op_source,
6115 buf_sprintf("`||` merges error sets; `or` performs boolean OR"));
6116 return ira->codegen->builtin_types.entry_invalid;
6117 }
6118
6119 ZigValue *const_val = ir_resolve_const(ira, type_value, UndefBad);
6120 if (!const_val)
6121 return ira->codegen->builtin_types.entry_invalid;
6122
6123 assert(const_val->data.x_type != nullptr);
6124 ZigType *result_type = const_val->data.x_type;
6125 if (result_type->id != ZigTypeIdErrorSet) {
6126 ErrorMsg *msg = ir_add_error_node(ira, type_value->source_node,
6127 buf_sprintf("expected error set type, found type '%s'", buf_ptr(&result_type->name)));
6128 add_error_note(ira->codegen, msg, op_source,
6129 buf_sprintf("`||` merges error sets; `or` performs boolean OR"));
6130 return ira->codegen->builtin_types.entry_invalid;
6131 }
6132 return result_type;
6133}
6134
6135static ZigFn *ir_resolve_fn(IrAnalyze *ira, Stage1AirInst *fn_value) {
6136 if (type_is_invalid(fn_value->value->type))
6137 return nullptr;
6138
6139 if (fn_value->value->type->id != ZigTypeIdFn) {
6140 ir_add_error_node(ira, fn_value->source_node,
6141 buf_sprintf("expected function type, found '%s'", buf_ptr(&fn_value->value->type->name)));
6142 return nullptr;
6143 }
6144
6145 ZigValue *const_val = ir_resolve_const(ira, fn_value, UndefBad);
6146 if (!const_val)
6147 return nullptr;
6148
6149 // May be a ConstPtrSpecialHardCodedAddr
6150 if (const_val->data.x_ptr.special != ConstPtrSpecialFunction)
6151 return nullptr;
6152
6153 return const_val->data.x_ptr.data.fn.fn_entry;
6154}
6155
6156static Stage1AirInst *ir_analyze_optional_wrap(IrAnalyze *ira, Scope *scope, AstNode *source_node,
6157 Stage1AirInst *value, ZigType *wanted_type, ResultLoc *result_loc)
6158{
6159 assert(wanted_type->id == ZigTypeIdOptional);
6160
6161 if (instr_is_comptime(value)) {
6162 ZigType *payload_type = wanted_type->data.maybe.child_type;
6163 Stage1AirInst *casted_payload = ir_implicit_cast(ira, value, payload_type);
6164 if (type_is_invalid(casted_payload->value->type))
6165 return ira->codegen->invalid_inst_gen;
6166
6167 ZigValue *val = ir_resolve_const(ira, casted_payload, UndefOk);
6168 if (!val)
6169 return ira->codegen->invalid_inst_gen;
6170
6171 Stage1AirInstConst *const_instruction = ir_create_inst_gen<Stage1AirInstConst>(&ira->new_irb,
6172 scope, source_node);
6173 const_instruction->base.value->special = ConstValSpecialStatic;
6174 if (types_have_same_zig_comptime_repr(ira->codegen, wanted_type, payload_type)) {
6175 copy_const_val(ira->codegen, const_instruction->base.value, val);
6176 } else {
6177 const_instruction->base.value->data.x_optional = val;
6178 }
6179 const_instruction->base.value->type = wanted_type;
6180 return &const_instruction->base;
6181 }
6182
6183 if (result_loc == nullptr && handle_is_ptr(ira->codegen, wanted_type)) {
6184 result_loc = no_result_loc();
6185 }
6186 Stage1AirInst *result_loc_inst = nullptr;
6187 if (result_loc != nullptr) {
6188 result_loc_inst = ir_resolve_result(ira, ira->suspend_source_instr, result_loc, wanted_type, nullptr, true, true);
6189 if (type_is_invalid(result_loc_inst->value->type) ||
6190 result_loc_inst->value->type->id == ZigTypeIdUnreachable)
6191 {
6192 return result_loc_inst;
6193 }
6194 }
6195 Stage1AirInst *result = ir_build_optional_wrap(ira, scope, source_node, wanted_type, value, result_loc_inst);
6196 result->value->data.rh_maybe = RuntimeHintOptionalNonNull;
6197 return result;
6198}
6199
6200static Stage1AirInst *ir_analyze_err_wrap_payload(IrAnalyze *ira, Scope *scope, AstNode *source_node,
6201 Stage1AirInst *value, ZigType *wanted_type, ResultLoc *result_loc)
6202{
6203 assert(wanted_type->id == ZigTypeIdErrorUnion);
6204
6205 ZigType *payload_type = wanted_type->data.error_union.payload_type;
6206 ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
6207 if (instr_is_comptime(value)) {
6208 Stage1AirInst *casted_payload = ir_implicit_cast(ira, value, payload_type);
6209 if (type_is_invalid(casted_payload->value->type))
6210 return ira->codegen->invalid_inst_gen;
6211
6212 ZigValue *val = ir_resolve_const(ira, casted_payload, UndefOk);
6213 if (val == nullptr)
6214 return ira->codegen->invalid_inst_gen;
6215
6216 ZigValue *err_set_val = ira->codegen->pass1_arena->create<ZigValue>();
6217 err_set_val->type = err_set_type;
6218 err_set_val->special = ConstValSpecialStatic;
6219 err_set_val->data.x_err_set = nullptr;
6220
6221 Stage1AirInstConst *const_instruction = ir_create_inst_gen<Stage1AirInstConst>(&ira->new_irb,
6222 scope, source_node);
6223 const_instruction->base.value->type = wanted_type;
6224 const_instruction->base.value->special = ConstValSpecialStatic;
6225 const_instruction->base.value->data.x_err_union.error_set = err_set_val;
6226 const_instruction->base.value->data.x_err_union.payload = val;
6227 return &const_instruction->base;
6228 }
6229
6230 Stage1AirInst *result_loc_inst;
6231 if (handle_is_ptr(ira->codegen, wanted_type)) {
6232 if (result_loc == nullptr) result_loc = no_result_loc();
6233 result_loc_inst = ir_resolve_result(ira, ira->suspend_source_instr, result_loc, wanted_type, nullptr, true, true);
6234 if (type_is_invalid(result_loc_inst->value->type) ||
6235 result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
6236 return result_loc_inst;
6237 }
6238 } else {
6239 result_loc_inst = nullptr;
6240 }
6241
6242 Stage1AirInst *result = ir_build_err_wrap_payload(ira, scope, source_node, wanted_type, value, result_loc_inst);
6243 result->value->data.rh_error_union = RuntimeHintErrorUnionNonError;
6244 return result;
6245}
6246
6247static Stage1AirInst *ir_analyze_err_set_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value,
6248 ZigType *wanted_type)
6249{
6250 assert(value->value->type->id == ZigTypeIdErrorSet);
6251 assert(wanted_type->id == ZigTypeIdErrorSet);
6252
6253 if (instr_is_comptime(value)) {
6254 ZigValue *val = ir_resolve_const(ira, value, UndefBad);
6255 if (!val)
6256 return ira->codegen->invalid_inst_gen;
6257
6258 if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_node)) {
6259 return ira->codegen->invalid_inst_gen;
6260 }
6261 if (!type_is_global_error_set(wanted_type)) {
6262 bool subset = false;
6263 for (uint32_t i = 0, count = wanted_type->data.error_set.err_count; i < count; i += 1) {
6264 if (wanted_type->data.error_set.errors[i]->value == val->data.x_err_set->value) {
6265 subset = true;
6266 break;
6267 }
6268 }
6269 if (!subset) {
6270 ir_add_error_node(ira, source_node,
6271 buf_sprintf("error.%s not a member of error set '%s'",
6272 buf_ptr(&val->data.x_err_set->name), buf_ptr(&wanted_type->name)));
6273 return ira->codegen->invalid_inst_gen;
6274 }
6275 }
6276
6277 Stage1AirInstConst *const_instruction = ir_create_inst_gen<Stage1AirInstConst>(&ira->new_irb,
6278 scope, source_node);
6279 const_instruction->base.value->type = wanted_type;
6280 const_instruction->base.value->special = ConstValSpecialStatic;
6281 const_instruction->base.value->data.x_err_set = val->data.x_err_set;
6282 return &const_instruction->base;
6283 }
6284
6285 return ir_build_cast(ira, scope, source_node, wanted_type, value, CastOpErrSet);
6286}
6287
6288static Stage1AirInst *ir_analyze_frame_ptr_to_anyframe(IrAnalyze *ira, Scope *scope, AstNode *source_node,
6289 Stage1AirInst *frame_ptr, ZigType *wanted_type)
6290{
6291 if (instr_is_comptime(frame_ptr)) {
6292 ZigValue *ptr_val = ir_resolve_const(ira, frame_ptr, UndefBad);
6293 if (ptr_val == nullptr)
6294 return ira->codegen->invalid_inst_gen;
6295
6296 src_assert(ptr_val->type->id == ZigTypeIdPointer, source_node );
6297 if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
6298 zig_panic("TODO comptime frame pointer");
6299 }
6300 }
6301
6302 return ir_build_cast(ira, scope, source_node, wanted_type, frame_ptr, CastOpBitCast);
6303}
6304
6305static Stage1AirInst *ir_analyze_anyframe_to_anyframe(IrAnalyze *ira, Scope *scope, AstNode *source_node,
6306 Stage1AirInst *value, ZigType *wanted_type)
6307{
6308 if (instr_is_comptime(value)) {
6309 zig_panic("TODO comptime anyframe->T to anyframe");
6310 }
6311
6312 return ir_build_cast(ira, scope, source_node, wanted_type, value, CastOpBitCast);
6313}
6314
6315
6316static Stage1AirInst *ir_analyze_err_wrap_code(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value,
6317 ZigType *wanted_type, ResultLoc *result_loc)
6318{
6319 assert(wanted_type->id == ZigTypeIdErrorUnion);
6320
6321 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, wanted_type->data.error_union.err_set_type);
6322
6323 if (instr_is_comptime(casted_value)) {
6324 ZigValue *val = ir_resolve_const(ira, casted_value, UndefBad);
6325 if (!val)
6326 return ira->codegen->invalid_inst_gen;
6327
6328 ZigValue *err_set_val = ira->codegen->pass1_arena->create<ZigValue>();
6329 err_set_val->special = ConstValSpecialStatic;
6330 err_set_val->type = wanted_type->data.error_union.err_set_type;
6331 err_set_val->data.x_err_set = val->data.x_err_set;
6332
6333 Stage1AirInstConst *const_instruction = ir_create_inst_gen<Stage1AirInstConst>(&ira->new_irb,
6334 scope, source_node);
6335 const_instruction->base.value->type = wanted_type;
6336 const_instruction->base.value->special = ConstValSpecialStatic;
6337 const_instruction->base.value->data.x_err_union.error_set = err_set_val;
6338 const_instruction->base.value->data.x_err_union.payload = nullptr;
6339 return &const_instruction->base;
6340 }
6341
6342 Stage1AirInst *result_loc_inst;
6343 if (handle_is_ptr(ira->codegen, wanted_type)) {
6344 if (result_loc == nullptr) result_loc = no_result_loc();
6345 result_loc_inst = ir_resolve_result(ira, ira->suspend_source_instr, result_loc, wanted_type, nullptr, true, true);
6346 if (type_is_invalid(result_loc_inst->value->type) ||
6347 result_loc_inst->value->type->id == ZigTypeIdUnreachable)
6348 {
6349 return result_loc_inst;
6350 }
6351 } else {
6352 result_loc_inst = nullptr;
6353 }
6354
6355
6356 Stage1AirInst *result = ir_build_err_wrap_code(ira, scope, source_node, wanted_type, value, result_loc_inst);
6357 result->value->data.rh_error_union = RuntimeHintErrorUnionError;
6358 return result;
6359}
6360
6361static Stage1AirInst *ir_analyze_null_to_maybe(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value, ZigType *wanted_type) {
6362 assert(wanted_type->id == ZigTypeIdOptional);
6363 assert(instr_is_comptime(value));
6364
6365 ZigValue *val = ir_resolve_const(ira, value, UndefBad);
6366 assert(val != nullptr);
6367
6368 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
6369 result->value->special = ConstValSpecialStatic;
6370
6371 if (get_src_ptr_type(wanted_type) != nullptr) {
6372 result->value->data.x_ptr.special = ConstPtrSpecialNull;
6373 } else if (is_opt_err_set(wanted_type)) {
6374 result->value->data.x_err_set = nullptr;
6375 } else {
6376 result->value->data.x_optional = nullptr;
6377 }
6378 return result;
6379}
6380
6381static Stage1AirInst *ir_analyze_null_to_c_pointer(IrAnalyze *ira, Scope *scope, AstNode *source_node,
6382 Stage1AirInst *value, ZigType *wanted_type)
6383{
6384 assert(wanted_type->id == ZigTypeIdPointer);
6385 assert(wanted_type->data.pointer.ptr_len == PtrLenC);
6386 assert(instr_is_comptime(value));
6387
6388 ZigValue *val = ir_resolve_const(ira, value, UndefBad);
6389 assert(val != nullptr);
6390
6391 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
6392 result->value->data.x_ptr.special = ConstPtrSpecialNull;
6393 result->value->data.x_ptr.mut = ConstPtrMutComptimeConst;
6394 return result;
6395}
6396
6397static Stage1AirInst *ir_get_ref2(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value,
6398 ZigType *elem_type, bool is_const, bool is_volatile)
6399{
6400 Error err;
6401
6402 if (type_is_invalid(elem_type))
6403 return ira->codegen->invalid_inst_gen;
6404
6405 if (instr_is_comptime(value)) {
6406 ZigValue *val = ir_resolve_const(ira, value, LazyOk);
6407 if (!val)
6408 return ira->codegen->invalid_inst_gen;
6409 return ir_get_const_ptr(ira, scope, source_node, val, elem_type,
6410 ConstPtrMutComptimeConst, is_const, is_volatile, 0);
6411 }
6412
6413 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, elem_type,
6414 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
6415
6416 if ((err = type_resolve(ira->codegen, ptr_type, ResolveStatusZeroBitsKnown)))
6417 return ira->codegen->invalid_inst_gen;
6418
6419 Stage1AirInst *result_loc;
6420 if (type_has_bits(ira->codegen, ptr_type) && !handle_is_ptr(ira->codegen, elem_type)) {
6421 result_loc = ir_resolve_result(ira, ira->suspend_source_instr, no_result_loc(), elem_type, nullptr, true, true);
6422 } else {
6423 result_loc = nullptr;
6424 }
6425
6426 Stage1AirInst *new_instruction = ir_build_ref_gen(ira, scope, source_node, ptr_type, value, result_loc);
6427 new_instruction->value->data.rh_ptr = RuntimeHintPtrStack;
6428 return new_instruction;
6429}
6430
6431static Stage1AirInst *ir_get_ref(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value,
6432 bool is_const, bool is_volatile)
6433{
6434 return ir_get_ref2(ira, scope, source_node, value, value->value->type, is_const, is_volatile);
6435}
6436
6437static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, AstNode *source_node, ZigType *union_type) {
6438 assert(union_type->id == ZigTypeIdUnion);
6439
6440 Error err;
6441 if ((err = type_resolve(ira->codegen, union_type, ResolveStatusSizeKnown)))
6442 return ira->codegen->builtin_types.entry_invalid;
6443
6444 AstNode *decl_node = union_type->data.unionation.decl_node;
6445 if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) {
6446 assert(union_type->data.unionation.tag_type != nullptr);
6447 return union_type->data.unionation.tag_type;
6448 } else {
6449 ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("union '%s' has no tag",
6450 buf_ptr(&union_type->name)));
6451 add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here"));
6452 return ira->codegen->builtin_types.entry_invalid;
6453 }
6454}
6455
6456static bool can_fold_enum_type(ZigType *ty) {
6457 assert(ty->id == ZigTypeIdEnum);
6458 // We can fold the enum type (and avoid any check, be it at runtime or at
6459 // compile time) iff it has only a single element and its tag type is
6460 // zero-sized.
6461 ZigType *tag_int_type = ty->data.enumeration.tag_int_type;
6462 return ty->data.enumeration.layout == ContainerLayoutAuto &&
6463 ty->data.enumeration.src_field_count == 1 &&
6464 !ty->data.enumeration.non_exhaustive &&
6465 (tag_int_type->id == ZigTypeIdInt && tag_int_type->data.integral.bit_count == 0);
6466}
6467
6468static Stage1AirInst *ir_analyze_enum_to_int(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *target) {
6469 Error err;
6470
6471 Stage1AirInst *enum_target;
6472 ZigType *enum_type;
6473 if (target->value->type->id == ZigTypeIdUnion) {
6474 enum_type = ir_resolve_union_tag_type(ira, target->source_node, target->value->type);
6475 if (type_is_invalid(enum_type))
6476 return ira->codegen->invalid_inst_gen;
6477 enum_target = ir_implicit_cast(ira, target, enum_type);
6478 if (type_is_invalid(enum_target->value->type))
6479 return ira->codegen->invalid_inst_gen;
6480 } else if (target->value->type->id == ZigTypeIdEnum) {
6481 enum_target = target;
6482 enum_type = target->value->type;
6483 } else {
6484 ir_add_error_node(ira, target->source_node,
6485 buf_sprintf("expected enum, found type '%s'", buf_ptr(&target->value->type->name)));
6486 return ira->codegen->invalid_inst_gen;
6487 }
6488
6489 if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusSizeKnown)))
6490 return ira->codegen->invalid_inst_gen;
6491
6492 ZigType *tag_type = enum_type->data.enumeration.tag_int_type;
6493 assert(tag_type->id == ZigTypeIdInt || tag_type->id == ZigTypeIdComptimeInt);
6494
6495 // If there is only one possible tag, then we know at comptime what it is.
6496 if (can_fold_enum_type(enum_type)) {
6497 Stage1AirInst *result = ir_const(ira, scope, source_node, tag_type);
6498 init_const_bigint(result->value, tag_type,
6499 &enum_type->data.enumeration.fields[0].value);
6500 return result;
6501 }
6502
6503 if (instr_is_comptime(enum_target)) {
6504 ZigValue *val = ir_resolve_const(ira, enum_target, UndefBad);
6505 if (!val)
6506 return ira->codegen->invalid_inst_gen;
6507 Stage1AirInst *result = ir_const(ira, scope, source_node, tag_type);
6508 init_const_bigint(result->value, tag_type, &val->data.x_enum_tag);
6509 return result;
6510 }
6511
6512 return ir_build_widen_or_shorten(ira, scope, source_node, enum_target, tag_type);
6513}
6514
6515static Stage1AirInst *ir_analyze_union_to_tag(IrAnalyze *ira, Scope *scope, AstNode *source_node,
6516 Stage1AirInst *target, ZigType *wanted_type)
6517{
6518 assert(target->value->type->id == ZigTypeIdUnion);
6519 assert(wanted_type->id == ZigTypeIdEnum);
6520 assert(wanted_type == target->value->type->data.unionation.tag_type);
6521
6522 if (instr_is_comptime(target)) {
6523 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
6524 if (!val)
6525 return ira->codegen->invalid_inst_gen;
6526 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
6527 result->value->special = ConstValSpecialStatic;
6528 result->value->type = wanted_type;
6529 bigint_init_bigint(&result->value->data.x_enum_tag, &val->data.x_union.tag);
6530 return result;
6531 }
6532
6533 // If there is only 1 possible tag, then we know at comptime what it is.
6534 if (can_fold_enum_type(wanted_type)) {
6535 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
6536 result->value->special = ConstValSpecialStatic;
6537 result->value->type = wanted_type;
6538 TypeEnumField *enum_field = target->value->type->data.unionation.fields[0].enum_field;
6539 bigint_init_bigint(&result->value->data.x_enum_tag, &enum_field->value);
6540 return result;
6541 }
6542
6543 return ir_build_union_tag(ira, scope, source_node, target, wanted_type);
6544}
6545
6546static Stage1AirInst *ir_analyze_undefined_to_anything(IrAnalyze *ira, Scope *scope, AstNode *source_node,
6547 Stage1AirInst *target, ZigType *wanted_type)
6548{
6549 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
6550 result->value->special = ConstValSpecialUndef;
6551 return result;
6552}
6553
6554static Stage1AirInst *ir_analyze_enum_to_union(IrAnalyze *ira, Scope *scope, AstNode *source_node,
6555 Stage1AirInst *uncasted_target, ZigType *wanted_type)
6556{
6557 Error err;
6558 assert(wanted_type->id == ZigTypeIdUnion);
6559
6560 if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown)))
6561 return ira->codegen->invalid_inst_gen;
6562
6563 Stage1AirInst *target = ir_implicit_cast(ira, uncasted_target, wanted_type->data.unionation.tag_type);
6564 if (type_is_invalid(target->value->type))
6565 return ira->codegen->invalid_inst_gen;
6566
6567 if (instr_is_comptime(target)) {
6568 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
6569 if (!val)
6570 return ira->codegen->invalid_inst_gen;
6571 TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag);
6572 if (union_field == nullptr) {
6573 Buf *int_buf = buf_alloc();
6574 bigint_append_buf(int_buf, &target->value->data.x_enum_tag, 10);
6575
6576 ir_add_error(ira, target,
6577 buf_sprintf("no tag by value %s", buf_ptr(int_buf)));
6578 return ira->codegen->invalid_inst_gen;
6579 }
6580 ZigType *field_type = resolve_union_field_type(ira->codegen, union_field);
6581 if (field_type == nullptr)
6582 return ira->codegen->invalid_inst_gen;
6583 if ((err = type_resolve(ira->codegen, field_type, ResolveStatusZeroBitsKnown)))
6584 return ira->codegen->invalid_inst_gen;
6585
6586 switch (type_has_one_possible_value(ira->codegen, field_type)) {
6587 case OnePossibleValueInvalid:
6588 return ira->codegen->invalid_inst_gen;
6589 case OnePossibleValueNo: {
6590 AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at(
6591 union_field->enum_field->decl_index);
6592 ErrorMsg *msg = ir_add_error_node(ira, source_node,
6593 buf_sprintf("cast to union '%s' must initialize '%s' field '%s'",
6594 buf_ptr(&wanted_type->name),
6595 buf_ptr(&field_type->name),
6596 buf_ptr(union_field->name)));
6597 add_error_note(ira->codegen, msg, field_node,
6598 buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));
6599 return ira->codegen->invalid_inst_gen;
6600 }
6601 case OnePossibleValueYes:
6602 break;
6603 }
6604
6605 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
6606 result->value->special = ConstValSpecialStatic;
6607 result->value->type = wanted_type;
6608 bigint_init_bigint(&result->value->data.x_union.tag, &val->data.x_enum_tag);
6609 result->value->data.x_union.payload = ira->codegen->pass1_arena->create<ZigValue>();
6610 result->value->data.x_union.payload->special = ConstValSpecialStatic;
6611 result->value->data.x_union.payload->type = field_type;
6612 return result;
6613 }
6614
6615 if (target->value->type->data.enumeration.non_exhaustive) {
6616 ir_add_error_node(ira, source_node,
6617 buf_sprintf("runtime cast to union '%s' from non-exhaustive enum",
6618 buf_ptr(&wanted_type->name)));
6619 return ira->codegen->invalid_inst_gen;
6620 }
6621
6622 // if the union has all fields 0 bits, we can do it
6623 // and in fact it's a noop cast because the union value is just the enum value
6624 if (wanted_type->data.unionation.gen_field_count == 0) {
6625 return ir_build_cast(ira, target->scope, target->source_node, wanted_type, target, CastOpNoop);
6626 }
6627
6628 ErrorMsg *msg = ir_add_error_node(ira, source_node,
6629 buf_sprintf("runtime cast to union '%s' which has non-void fields",
6630 buf_ptr(&wanted_type->name)));
6631 for (uint32_t i = 0; i < wanted_type->data.unionation.src_field_count; i += 1) {
6632 TypeUnionField *union_field = &wanted_type->data.unionation.fields[i];
6633 ZigType *field_type = resolve_union_field_type(ira->codegen, union_field);
6634 if (field_type == nullptr)
6635 return ira->codegen->invalid_inst_gen;
6636 bool has_bits;
6637 if ((err = type_has_bits2(ira->codegen, field_type, &has_bits)))
6638 return ira->codegen->invalid_inst_gen;
6639 if (has_bits) {
6640 AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at(i);
6641 add_error_note(ira->codegen, msg, field_node,
6642 buf_sprintf("field '%s' has type '%s'",
6643 buf_ptr(union_field->name),
6644 buf_ptr(&field_type->name)));
6645 }
6646 }
6647 return ira->codegen->invalid_inst_gen;
6648}
6649
6650static bool value_numeric_fits_in_type(ZigValue *value, ZigType *type_entry);
6651
6652static Stage1AirInst *ir_analyze_widen_or_shorten(IrAnalyze *ira, Scope *scope, AstNode *source_node,
6653 Stage1AirInst *target, ZigType *wanted_type)
6654{
6655 ZigType *wanted_scalar_type = (target->value->type->id == ZigTypeIdVector) ?
6656 wanted_type->data.vector.elem_type : wanted_type;
6657
6658 assert(wanted_scalar_type->id == ZigTypeIdInt || wanted_scalar_type->id == ZigTypeIdFloat);
6659
6660 if (instr_is_comptime(target)) {
6661 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
6662 if (!val)
6663 return ira->codegen->invalid_inst_gen;
6664
6665 if (wanted_scalar_type->id == ZigTypeIdInt) {
6666 if (!wanted_scalar_type->data.integral.is_signed && value_cmp_numeric_val_any(val, CmpLT, nullptr)) {
6667 ir_add_error_node(ira, source_node,
6668 buf_sprintf("attempt to cast negative value to unsigned integer"));
6669 return ira->codegen->invalid_inst_gen;
6670 }
6671 if (!value_numeric_fits_in_type(val, wanted_scalar_type)) {
6672 ir_add_error_node(ira, source_node,
6673 buf_sprintf("cast from '%s' to '%s' truncates bits",
6674 buf_ptr(&target->value->type->name), buf_ptr(&wanted_scalar_type->name)));
6675 return ira->codegen->invalid_inst_gen;
6676 }
6677 }
6678
6679 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
6680 result->value->type = wanted_type;
6681
6682 if (wanted_type->id == ZigTypeIdVector) {
6683 result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(wanted_type->data.vector.len);
6684
6685 for (size_t i = 0; i < wanted_type->data.vector.len; i++) {
6686 ZigValue *scalar_dest_value = &result->value->data.x_array.data.s_none.elements[i];
6687 ZigValue *scalar_src_value = &val->data.x_array.data.s_none.elements[i];
6688
6689 scalar_dest_value->type = wanted_scalar_type;
6690 scalar_dest_value->special = ConstValSpecialStatic;
6691
6692 if (wanted_scalar_type->id == ZigTypeIdInt) {
6693 bigint_init_bigint(&scalar_dest_value->data.x_bigint, &scalar_src_value->data.x_bigint);
6694 } else {
6695 float_init_float(scalar_dest_value, scalar_src_value);
6696 }
6697 }
6698 } else {
6699 if (wanted_type->id == ZigTypeIdInt) {
6700 bigint_init_bigint(&result->value->data.x_bigint, &val->data.x_bigint);
6701 } else {
6702 float_init_float(result->value, val);
6703 }
6704 }
6705
6706 return result;
6707 }
6708
6709 // If the destination integer type has no bits, then we can emit a comptime
6710 // zero. However, we still want to emit a runtime safety check to make sure
6711 // the target is zero.
6712 if (!type_has_bits(ira->codegen, wanted_type)) {
6713 assert(wanted_type->id == ZigTypeIdInt);
6714 assert(type_has_bits(ira->codegen, target->value->type));
6715 ir_build_assert_zero(ira, scope, source_node, target);
6716 Stage1AirInst *result = ir_const_unsigned(ira, scope, source_node, 0);
6717 result->value->type = wanted_type;
6718 return result;
6719 }
6720
6721 return ir_build_widen_or_shorten(ira, scope, source_node, target, wanted_type);
6722}
6723
6724static Stage1AirInst *ir_analyze_int_to_enum(IrAnalyze *ira, Scope *scope, AstNode *source_node,
6725 Stage1AirInst *target, ZigType *wanted_type)
6726{
6727 Error err;
6728 assert(wanted_type->id == ZigTypeIdEnum);
6729
6730 ZigType *actual_type = target->value->type;
6731
6732 if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusSizeKnown)))
6733 return ira->codegen->invalid_inst_gen;
6734
6735 if (actual_type != wanted_type->data.enumeration.tag_int_type) {
6736 ir_add_error_node(ira, source_node,
6737 buf_sprintf("integer to enum cast from '%s' instead of its tag type, '%s'",
6738 buf_ptr(&actual_type->name),
6739 buf_ptr(&wanted_type->data.enumeration.tag_int_type->name)));
6740 return ira->codegen->invalid_inst_gen;
6741 }
6742
6743 assert(actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt);
6744
6745 if (instr_is_comptime(target)) {
6746 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
6747 if (!val)
6748 return ira->codegen->invalid_inst_gen;
6749
6750 TypeEnumField *field = find_enum_field_by_tag(wanted_type, &val->data.x_bigint);
6751 if (field == nullptr && !wanted_type->data.enumeration.non_exhaustive) {
6752 Buf *val_buf = buf_alloc();
6753 bigint_append_buf(val_buf, &val->data.x_bigint, 10);
6754 ErrorMsg *msg = ir_add_error_node(ira, source_node,
6755 buf_sprintf("enum '%s' has no tag matching integer value %s",
6756 buf_ptr(&wanted_type->name), buf_ptr(val_buf)));
6757 add_error_note(ira->codegen, msg, wanted_type->data.enumeration.decl_node,
6758 buf_sprintf("'%s' declared here", buf_ptr(&wanted_type->name)));
6759 return ira->codegen->invalid_inst_gen;
6760 }
6761
6762 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
6763 bigint_init_bigint(&result->value->data.x_enum_tag, &val->data.x_bigint);
6764 return result;
6765 }
6766
6767 return ir_build_int_to_enum_gen(ira, scope, source_node, wanted_type, target);
6768}
6769
6770static Stage1AirInst *ir_analyze_number_to_literal(IrAnalyze *ira, Scope *scope, AstNode *source_node,
6771 Stage1AirInst *target, ZigType *wanted_type)
6772{
6773 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
6774 if (!val)
6775 return ira->codegen->invalid_inst_gen;
6776
6777 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
6778 if (wanted_type->id == ZigTypeIdComptimeFloat) {
6779 float_init_float(result->value, val);
6780 } else if (wanted_type->id == ZigTypeIdComptimeInt) {
6781 bigint_init_bigint(&result->value->data.x_bigint, &val->data.x_bigint);
6782 } else {
6783 zig_unreachable();
6784 }
6785 return result;
6786}
6787
6788static Stage1AirInst *ir_analyze_int_to_err(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *target,
6789 ZigType *wanted_type)
6790{
6791 assert(target->value->type->id == ZigTypeIdInt);
6792 assert(!target->value->type->data.integral.is_signed);
6793 assert(wanted_type->id == ZigTypeIdErrorSet);
6794
6795 if (instr_is_comptime(target)) {
6796 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
6797 if (!val)
6798 return ira->codegen->invalid_inst_gen;
6799
6800 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
6801
6802 if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_node)) {
6803 return ira->codegen->invalid_inst_gen;
6804 }
6805
6806 if (type_is_global_error_set(wanted_type)) {
6807 BigInt err_count;
6808 bigint_init_unsigned(&err_count, ira->codegen->errors_by_index.length);
6809
6810 if (bigint_cmp_zero(&val->data.x_bigint) == CmpEQ || bigint_cmp(&val->data.x_bigint, &err_count) != CmpLT) {
6811 Buf *val_buf = buf_alloc();
6812 bigint_append_buf(val_buf, &val->data.x_bigint, 10);
6813 ir_add_error_node(ira, source_node,
6814 buf_sprintf("integer value %s represents no error", buf_ptr(val_buf)));
6815 return ira->codegen->invalid_inst_gen;
6816 }
6817
6818 size_t index = bigint_as_usize(&val->data.x_bigint);
6819 result->value->data.x_err_set = ira->codegen->errors_by_index.at(index);
6820 return result;
6821 } else {
6822 ErrorTableEntry *err = nullptr;
6823 BigInt err_int;
6824
6825 for (uint32_t i = 0, count = wanted_type->data.error_set.err_count; i < count; i += 1) {
6826 ErrorTableEntry *this_err = wanted_type->data.error_set.errors[i];
6827 bigint_init_unsigned(&err_int, this_err->value);
6828 if (bigint_cmp(&val->data.x_bigint, &err_int) == CmpEQ) {
6829 err = this_err;
6830 break;
6831 }
6832 }
6833
6834 if (err == nullptr) {
6835 Buf *val_buf = buf_alloc();
6836 bigint_append_buf(val_buf, &val->data.x_bigint, 10);
6837 ir_add_error_node(ira, source_node,
6838 buf_sprintf("integer value %s represents no error in '%s'", buf_ptr(val_buf), buf_ptr(&wanted_type->name)));
6839 return ira->codegen->invalid_inst_gen;
6840 }
6841
6842 result->value->data.x_err_set = err;
6843 return result;
6844 }
6845 }
6846
6847 return ir_build_int_to_err_gen(ira, scope, source_node, target, wanted_type);
6848}
6849
6850static Stage1AirInst *ir_analyze_err_to_int(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *target,
6851 ZigType *wanted_type)
6852{
6853 assert(wanted_type->id == ZigTypeIdInt);
6854
6855 ZigType *err_type = target->value->type;
6856
6857 if (instr_is_comptime(target)) {
6858 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
6859 if (!val)
6860 return ira->codegen->invalid_inst_gen;
6861
6862 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
6863
6864 ErrorTableEntry *err;
6865 if (err_type->id == ZigTypeIdErrorUnion) {
6866 err = val->data.x_err_union.error_set->data.x_err_set;
6867 } else if (err_type->id == ZigTypeIdErrorSet) {
6868 err = val->data.x_err_set;
6869 } else {
6870 zig_unreachable();
6871 }
6872 result->value->type = wanted_type;
6873 uint64_t err_value = err ? err->value : 0;
6874 bigint_init_unsigned(&result->value->data.x_bigint, err_value);
6875
6876 if (!bigint_fits_in_bits(&result->value->data.x_bigint,
6877 wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed))
6878 {
6879 ir_add_error_node(ira, source_node,
6880 buf_sprintf("error code '%s' does not fit in '%s'",
6881 buf_ptr(&err->name), buf_ptr(&wanted_type->name)));
6882 return ira->codegen->invalid_inst_gen;
6883 }
6884
6885 return result;
6886 }
6887
6888 ZigType *err_set_type;
6889 if (err_type->id == ZigTypeIdErrorUnion) {
6890 err_set_type = err_type->data.error_union.err_set_type;
6891 } else if (err_type->id == ZigTypeIdErrorSet) {
6892 err_set_type = err_type;
6893 } else {
6894 zig_unreachable();
6895 }
6896 if (!type_is_global_error_set(err_set_type)) {
6897 if (!resolve_inferred_error_set(ira->codegen, err_set_type, source_node)) {
6898 return ira->codegen->invalid_inst_gen;
6899 }
6900 if (err_set_type->data.error_set.err_count == 0) {
6901 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
6902 bigint_init_unsigned(&result->value->data.x_bigint, 0);
6903 return result;
6904 } else if (err_set_type->data.error_set.err_count == 1) {
6905 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
6906 ErrorTableEntry *err = err_set_type->data.error_set.errors[0];
6907 bigint_init_unsigned(&result->value->data.x_bigint, err->value);
6908 return result;
6909 }
6910 }
6911
6912 BigInt bn;
6913 bigint_init_unsigned(&bn, ira->codegen->errors_by_index.length);
6914 if (!bigint_fits_in_bits(&bn, wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed)) {
6915 ir_add_error_node(ira, source_node,
6916 buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name)));
6917 return ira->codegen->invalid_inst_gen;
6918 }
6919
6920 return ir_build_err_to_int_gen(ira, scope, source_node, target, wanted_type);
6921}
6922
6923static Stage1AirInst *ir_analyze_ptr_to_array(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *target,
6924 ZigType *wanted_type)
6925{
6926 assert(wanted_type->id == ZigTypeIdPointer);
6927 Error err;
6928 if ((err = type_resolve(ira->codegen, target->value->type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
6929 return ira->codegen->invalid_inst_gen;
6930 assert((wanted_type->data.pointer.is_const && target->value->type->data.pointer.is_const) || !target->value->type->data.pointer.is_const);
6931 wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, target->value->type));
6932 ZigType *array_type = wanted_type->data.pointer.child_type;
6933 assert(array_type->id == ZigTypeIdArray);
6934 assert(array_type->data.array.len == 1);
6935
6936 if (instr_is_comptime(target)) {
6937 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
6938 if (!val)
6939 return ira->codegen->invalid_inst_gen;
6940
6941 assert(val->type->id == ZigTypeIdPointer);
6942 ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, val, source_node);
6943 if (pointee == nullptr)
6944 return ira->codegen->invalid_inst_gen;
6945 if (pointee->special != ConstValSpecialRuntime) {
6946 ZigValue *array_val = ira->codegen->pass1_arena->create<ZigValue>();
6947 array_val->special = ConstValSpecialStatic;
6948 array_val->type = array_type;
6949 array_val->data.x_array.special = ConstArraySpecialNone;
6950 array_val->data.x_array.data.s_none.elements = pointee;
6951 array_val->parent.id = ConstParentIdScalar;
6952 array_val->parent.data.p_scalar.scalar_val = pointee;
6953
6954 Stage1AirInstConst *const_instruction = ir_create_inst_gen<Stage1AirInstConst>(&ira->new_irb,
6955 scope, source_node);
6956 const_instruction->base.value->type = wanted_type;
6957 const_instruction->base.value->special = ConstValSpecialStatic;
6958 const_instruction->base.value->data.x_ptr.special = ConstPtrSpecialRef;
6959 const_instruction->base.value->data.x_ptr.data.ref.pointee = array_val;
6960 const_instruction->base.value->data.x_ptr.mut = val->data.x_ptr.mut;
6961 return &const_instruction->base;
6962 }
6963 }
6964
6965 // pointer to array and pointer to single item are represented the same way at runtime
6966 return ir_build_cast(ira, target->scope, target->source_node, wanted_type, target, CastOpBitCast);
6967}
6968
6969static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCastOnly *cast_result,
6970 ErrorMsg *parent_msg)
6971{
6972 switch (cast_result->id) {
6973 case ConstCastResultIdOk:
6974 zig_unreachable();
6975 case ConstCastResultIdInvalid:
6976 zig_unreachable();
6977 case ConstCastResultIdOptionalChild: {
6978 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
6979 buf_sprintf("optional type child '%s' cannot cast into optional type child '%s'",
6980 buf_ptr(&cast_result->data.optional->actual_child->name),
6981 buf_ptr(&cast_result->data.optional->wanted_child->name)));
6982 report_recursive_error(ira, source_node, &cast_result->data.optional->child, msg);
6983 break;
6984 }
6985 case ConstCastResultIdOptionalShape: {
6986 add_error_note(ira->codegen, parent_msg, source_node,
6987 buf_sprintf("optional type child '%s' cannot cast into optional type '%s'",
6988 buf_ptr(&cast_result->data.type_mismatch->actual_type->name),
6989 buf_ptr(&cast_result->data.type_mismatch->wanted_type->name)));
6990 break;
6991 }
6992 case ConstCastResultIdErrorUnionErrorSet: {
6993 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
6994 buf_sprintf("error set '%s' cannot cast into error set '%s'",
6995 buf_ptr(&cast_result->data.error_union_error_set->actual_err_set->name),
6996 buf_ptr(&cast_result->data.error_union_error_set->wanted_err_set->name)));
6997 report_recursive_error(ira, source_node, &cast_result->data.error_union_error_set->child, msg);
6998 break;
6999 }
7000 case ConstCastResultIdErrSet: {
7001 ZigList<ErrorTableEntry *> *missing_errors = &cast_result->data.error_set_mismatch->missing_errors;
7002 for (size_t i = 0; i < missing_errors->length; i += 1) {
7003 ErrorTableEntry *error_entry = missing_errors->at(i);
7004 add_error_note(ira->codegen, parent_msg, ast_field_to_symbol_node(error_entry->decl_node),
7005 buf_sprintf("'error.%s' not a member of destination error set", buf_ptr(&error_entry->name)));
7006 }
7007 break;
7008 }
7009 case ConstCastResultIdErrSetGlobal: {
7010 add_error_note(ira->codegen, parent_msg, source_node,
7011 buf_sprintf("cannot cast global error set into smaller set"));
7012 break;
7013 }
7014 case ConstCastResultIdPointerChild: {
7015 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
7016 buf_sprintf("pointer type child '%s' cannot cast into pointer type child '%s'",
7017 buf_ptr(&cast_result->data.pointer_mismatch->actual_child->name),
7018 buf_ptr(&cast_result->data.pointer_mismatch->wanted_child->name)));
7019 report_recursive_error(ira, source_node, &cast_result->data.pointer_mismatch->child, msg);
7020 break;
7021 }
7022 case ConstCastResultIdSliceChild: {
7023 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
7024 buf_sprintf("slice type child '%s' cannot cast into slice type child '%s'",
7025 buf_ptr(&cast_result->data.slice_mismatch->actual_child->name),
7026 buf_ptr(&cast_result->data.slice_mismatch->wanted_child->name)));
7027 report_recursive_error(ira, source_node, &cast_result->data.slice_mismatch->child, msg);
7028 break;
7029 }
7030 case ConstCastResultIdErrorUnionPayload: {
7031 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
7032 buf_sprintf("error union payload '%s' cannot cast into error union payload '%s'",
7033 buf_ptr(&cast_result->data.error_union_payload->actual_payload->name),
7034 buf_ptr(&cast_result->data.error_union_payload->wanted_payload->name)));
7035 report_recursive_error(ira, source_node, &cast_result->data.error_union_payload->child, msg);
7036 break;
7037 }
7038 case ConstCastResultIdType: {
7039 AstNode *wanted_decl_node = type_decl_node(cast_result->data.type_mismatch->wanted_type);
7040 AstNode *actual_decl_node = type_decl_node(cast_result->data.type_mismatch->actual_type);
7041 if (wanted_decl_node != nullptr) {
7042 add_error_note(ira->codegen, parent_msg, wanted_decl_node,
7043 buf_sprintf("%s declared here",
7044 buf_ptr(&cast_result->data.type_mismatch->wanted_type->name)));
7045 }
7046 if (actual_decl_node != nullptr) {
7047 add_error_note(ira->codegen, parent_msg, actual_decl_node,
7048 buf_sprintf("%s declared here",
7049 buf_ptr(&cast_result->data.type_mismatch->actual_type->name)));
7050 }
7051 break;
7052 }
7053 case ConstCastResultIdFnArg: {
7054 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
7055 buf_sprintf("parameter %" ZIG_PRI_usize ": '%s' cannot cast into '%s'",
7056 cast_result->data.fn_arg.arg_index,
7057 buf_ptr(&cast_result->data.fn_arg.actual_param_type->name),
7058 buf_ptr(&cast_result->data.fn_arg.expected_param_type->name)));
7059 report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);
7060 break;
7061 }
7062 case ConstCastResultIdBadAllowsZero: {
7063 ZigType *wanted_type = cast_result->data.bad_allows_zero->wanted_type;
7064 ZigType *actual_type = cast_result->data.bad_allows_zero->actual_type;
7065 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
7066 bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
7067 if (actual_allows_zero && !wanted_allows_zero) {
7068 add_error_note(ira->codegen, parent_msg, source_node,
7069 buf_sprintf("'%s' could have null values which are illegal in type '%s'",
7070 buf_ptr(&actual_type->name),
7071 buf_ptr(&wanted_type->name)));
7072 } else {
7073 add_error_note(ira->codegen, parent_msg, source_node,
7074 buf_sprintf("mutable '%s' allows illegal null values stored to type '%s'",
7075 buf_ptr(&wanted_type->name),
7076 buf_ptr(&actual_type->name)));
7077 }
7078 break;
7079 }
7080 case ConstCastResultIdPtrLens: {
7081 add_error_note(ira->codegen, parent_msg, source_node,
7082 buf_sprintf("pointer length mismatch"));
7083 break;
7084 }
7085 case ConstCastResultIdPtrSentinel: {
7086 ZigType *actual_type = cast_result->data.bad_ptr_sentinel->actual_type;
7087 ZigType *wanted_type = cast_result->data.bad_ptr_sentinel->wanted_type;
7088 {
7089 Buf *txt_msg = buf_sprintf("destination pointer requires a terminating '");
7090 render_const_value(ira->codegen, txt_msg, wanted_type->data.pointer.sentinel);
7091 buf_appendf(txt_msg, "' sentinel");
7092 if (actual_type->data.pointer.sentinel != nullptr) {
7093 buf_appendf(txt_msg, ", but source pointer has a terminating '");
7094 render_const_value(ira->codegen, txt_msg, actual_type->data.pointer.sentinel);
7095 buf_appendf(txt_msg, "' sentinel");
7096 }
7097 add_error_note(ira->codegen, parent_msg, source_node, txt_msg);
7098 }
7099 break;
7100 }
7101 case ConstCastResultIdSentinelArrays: {
7102 ZigType *actual_type = cast_result->data.sentinel_arrays->actual_type;
7103 ZigType *wanted_type = cast_result->data.sentinel_arrays->wanted_type;
7104 Buf *txt_msg = buf_sprintf("destination array requires a terminating '");
7105 render_const_value(ira->codegen, txt_msg, wanted_type->data.array.sentinel);
7106 buf_appendf(txt_msg, "' sentinel");
7107 if (actual_type->data.array.sentinel != nullptr) {
7108 buf_appendf(txt_msg, ", but source array has a terminating '");
7109 render_const_value(ira->codegen, txt_msg, actual_type->data.array.sentinel);
7110 buf_appendf(txt_msg, "' sentinel");
7111 }
7112 add_error_note(ira->codegen, parent_msg, source_node, txt_msg);
7113 break;
7114 }
7115 case ConstCastResultIdCV: {
7116 ZigType *wanted_type = cast_result->data.bad_cv->wanted_type;
7117 ZigType *actual_type = cast_result->data.bad_cv->actual_type;
7118 bool ok_const = !actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const;
7119 bool ok_volatile = !actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile;
7120 if (!ok_const) {
7121 add_error_note(ira->codegen, parent_msg, source_node, buf_sprintf("cast discards const qualifier"));
7122 } else if (!ok_volatile) {
7123 add_error_note(ira->codegen, parent_msg, source_node, buf_sprintf("cast discards volatile qualifier"));
7124 } else {
7125 zig_unreachable();
7126 }
7127 break;
7128 }
7129 case ConstCastResultIdFnIsGeneric:
7130 add_error_note(ira->codegen, parent_msg, source_node,
7131 buf_sprintf("only one of the functions is generic"));
7132 break;
7133 case ConstCastResultIdFnCC:
7134 add_error_note(ira->codegen, parent_msg, source_node,
7135 buf_sprintf("calling convention mismatch"));
7136 break;
7137 case ConstCastResultIdIntShorten: {
7138 ZigType *wanted_type = cast_result->data.int_shorten->wanted_type;
7139 ZigType *actual_type = cast_result->data.int_shorten->actual_type;
7140 const char *wanted_signed = wanted_type->data.integral.is_signed ? "signed" : "unsigned";
7141 const char *actual_signed = actual_type->data.integral.is_signed ? "signed" : "unsigned";
7142 add_error_note(ira->codegen, parent_msg, source_node,
7143 buf_sprintf("%s %" PRIu32 "-bit int cannot represent all possible %s %" PRIu32 "-bit values",
7144 wanted_signed, wanted_type->data.integral.bit_count,
7145 actual_signed, actual_type->data.integral.bit_count));
7146 break;
7147 }
7148 case ConstCastResultIdVectorLength: // TODO
7149 case ConstCastResultIdVectorChild: // TODO
7150 case ConstCastResultIdFnAlign: // TODO
7151 case ConstCastResultIdFnVarArgs: // TODO
7152 case ConstCastResultIdFnReturnType: // TODO
7153 case ConstCastResultIdFnArgCount: // TODO
7154 case ConstCastResultIdFnGenericArgCount: // TODO
7155 case ConstCastResultIdFnArgNoAlias: // TODO
7156 case ConstCastResultIdUnresolvedInferredErrSet: // TODO
7157 case ConstCastResultIdAsyncAllocatorType: // TODO
7158 case ConstCastResultIdArrayChild: // TODO
7159 break;
7160 }
7161}
7162
7163static Stage1AirInst *ir_analyze_array_to_vector(IrAnalyze *ira, Scope *scope, AstNode *source_node,
7164 Stage1AirInst *array, ZigType *vector_type)
7165{
7166 if (instr_is_comptime(array)) {
7167 // arrays and vectors have the same ZigValue representation
7168 Stage1AirInst *result = ir_const(ira, scope, source_node, vector_type);
7169 copy_const_val(ira->codegen, result->value, array->value);
7170 result->value->type = vector_type;
7171 return result;
7172 }
7173 return ir_build_array_to_vector(ira, scope, source_node, array, vector_type);
7174}
7175
7176static Stage1AirInst *ir_analyze_vector_to_array(IrAnalyze *ira, Scope *scope, AstNode *source_node,
7177 Stage1AirInst *vector, ZigType *array_type, ResultLoc *result_loc)
7178{
7179 if (instr_is_comptime(vector)) {
7180 // arrays and vectors have the same ZigValue representation
7181 Stage1AirInst *result = ir_const(ira, scope, source_node, array_type);
7182 copy_const_val(ira->codegen, result->value, vector->value);
7183 result->value->type = array_type;
7184 return result;
7185 }
7186 if (result_loc == nullptr) {
7187 result_loc = no_result_loc();
7188 }
7189 Stage1AirInst *result_loc_inst = ir_resolve_result(ira, ira->suspend_source_instr, result_loc, array_type, nullptr, true, true);
7190 if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
7191 return result_loc_inst;
7192 }
7193 return ir_build_vector_to_array(ira, scope, source_node, array_type, vector, result_loc_inst);
7194}
7195
7196static Stage1AirInst *ir_analyze_int_to_c_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node,
7197 Stage1AirInst *integer, ZigType *dest_type)
7198{
7199 Stage1AirInst *unsigned_integer;
7200 if (instr_is_comptime(integer)) {
7201 unsigned_integer = integer;
7202 } else {
7203 assert(integer->value->type->id == ZigTypeIdInt);
7204
7205 if (integer->value->type->data.integral.bit_count >
7206 ira->codegen->builtin_types.entry_usize->data.integral.bit_count)
7207 {
7208 ir_add_error_node(ira, source_node,
7209 buf_sprintf("integer type '%s' too big for implicit @intToPtr to type '%s'",
7210 buf_ptr(&integer->value->type->name),
7211 buf_ptr(&dest_type->name)));
7212 return ira->codegen->invalid_inst_gen;
7213 }
7214
7215 if (integer->value->type->data.integral.is_signed) {
7216 ZigType *unsigned_int_type = get_int_type(ira->codegen, false,
7217 integer->value->type->data.integral.bit_count);
7218 unsigned_integer = ir_analyze_bit_cast(ira, scope, source_node, integer, unsigned_int_type);
7219 if (type_is_invalid(unsigned_integer->value->type))
7220 return ira->codegen->invalid_inst_gen;
7221 } else {
7222 unsigned_integer = integer;
7223 }
7224 }
7225
7226 return ir_analyze_int_to_ptr(ira, scope, source_node, unsigned_integer, dest_type);
7227}
7228
7229static bool is_pointery_and_elem_is_not_pointery(ZigType *ty) {
7230 if (ty->id == ZigTypeIdPointer) return ty->data.pointer.child_type->id != ZigTypeIdPointer;
7231 if (ty->id == ZigTypeIdFn) return true;
7232 if (ty->id == ZigTypeIdOptional) {
7233 ZigType *ptr_ty = ty->data.maybe.child_type;
7234 if (ptr_ty->id == ZigTypeIdPointer) return ptr_ty->data.pointer.child_type->id != ZigTypeIdPointer;
7235 if (ptr_ty->id == ZigTypeIdFn) return true;
7236 }
7237 return false;
7238}
7239
7240static Stage1AirInst *ir_analyze_enum_literal(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value,
7241 ZigType *enum_type)
7242{
7243 assert(enum_type->id == ZigTypeIdEnum);
7244
7245 Error err;
7246 if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusZeroBitsKnown)))
7247 return ira->codegen->invalid_inst_gen;
7248
7249 TypeEnumField *field = find_enum_type_field(enum_type, value->value->data.x_enum_literal);
7250 if (field == nullptr) {
7251 ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("enum '%s' has no field named '%s'",
7252 buf_ptr(&enum_type->name), buf_ptr(value->value->data.x_enum_literal)));
7253 add_error_note(ira->codegen, msg, enum_type->data.enumeration.decl_node,
7254 buf_sprintf("'%s' declared here", buf_ptr(&enum_type->name)));
7255 return ira->codegen->invalid_inst_gen;
7256 }
7257 Stage1AirInst *result = ir_const(ira, scope, source_node, enum_type);
7258 bigint_init_bigint(&result->value->data.x_enum_tag, &field->value);
7259
7260 return result;
7261}
7262
7263static Stage1AirInst *ir_analyze_struct_literal_to_array(IrAnalyze *ira, Scope *scope, AstNode *source_node,
7264 Stage1AirInst *struct_ptr, ZigType *actual_type, ZigType *wanted_type)
7265{
7266 Error err;
7267
7268 if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusSizeKnown)))
7269 return ira->codegen->invalid_inst_gen;
7270
7271 size_t array_len = wanted_type->data.array.len;
7272 size_t instr_field_count = actual_type->data.structure.src_field_count;
7273 assert(array_len == instr_field_count);
7274
7275 bool need_comptime = ir_should_inline(ira->zir, scope)
7276 || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes;
7277 bool is_comptime = true;
7278
7279 ZigType *elem_type = wanted_type->data.array.child_type;
7280
7281 // Determine if the struct_operand will be comptime.
7282 ZigValue *elem_values = heap::c_allocator.allocate<ZigValue>(array_len);
7283 Stage1AirInst **casted_fields = heap::c_allocator.allocate<Stage1AirInst *>(array_len);
7284 Stage1AirInst *const_result = ir_const(ira, scope, source_node, wanted_type);
7285
7286 for (size_t i = 0; i < array_len; i += 1) {
7287 TypeStructField *src_field = actual_type->data.structure.fields[i];
7288
7289 Stage1AirInst *field_ptr = ir_analyze_struct_field_ptr(ira, scope, source_node, src_field, struct_ptr,
7290 actual_type, false);
7291 if (type_is_invalid(field_ptr->value->type))
7292 return ira->codegen->invalid_inst_gen;
7293 Stage1AirInst *field_value = ir_get_deref(ira, scope, source_node, field_ptr, nullptr);
7294 if (type_is_invalid(field_value->value->type))
7295 return ira->codegen->invalid_inst_gen;
7296 Stage1AirInst *casted_value = ir_implicit_cast(ira, field_value, elem_type);
7297 if (type_is_invalid(casted_value->value->type))
7298 return ira->codegen->invalid_inst_gen;
7299
7300 casted_fields[i] = casted_value;
7301 if (need_comptime || instr_is_comptime(casted_value)) {
7302 ZigValue *field_val = ir_resolve_const(ira, casted_value, UndefOk);
7303 if (field_val == nullptr)
7304 return ira->codegen->invalid_inst_gen;
7305
7306 field_val->parent.id = ConstParentIdArray;
7307 field_val->parent.data.p_array.array_val = const_result->value;
7308 field_val->parent.data.p_array.elem_index = i;
7309 elem_values[i] = *field_val;
7310 if (field_val->type->id == ZigTypeIdUndefined) {
7311 elem_values[i].special = ConstValSpecialUndef;
7312 }
7313 } else {
7314 is_comptime = false;
7315 }
7316 }
7317
7318 if (is_comptime) {
7319 Stage1AirInst *const_result = ir_const(ira, scope, source_node, wanted_type);
7320 const_result->value->data.x_array.special = ConstArraySpecialNone;
7321 const_result->value->data.x_array.data.s_none.elements = elem_values;
7322 return const_result;
7323 }
7324
7325 Stage1AirInst *result_loc_inst = ir_resolve_result(ira, ira->suspend_source_instr, no_result_loc(),
7326 wanted_type, nullptr, true, true);
7327 if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
7328 return ira->codegen->invalid_inst_gen;
7329 }
7330
7331 ZigType *elem_type_ptr = get_pointer_to_type(ira->codegen, elem_type, false);
7332 for (size_t i = 0; i < array_len; i += 1) {
7333 Stage1AirInst *index_val = ir_const(ira, scope, source_node, ira->codegen->builtin_types.entry_usize);
7334 bigint_init_unsigned(&index_val->value->data.x_bigint, i);
7335
7336 Stage1AirInst *elem_ptr = ir_build_elem_ptr_gen(ira, scope, source_node,
7337 result_loc_inst, index_val, false, elem_type_ptr);
7338 Stage1AirInst *store_ptr_inst = ir_analyze_store_ptr(ira, scope, source_node, elem_ptr, casted_fields[i], true);
7339 if (type_is_invalid(store_ptr_inst->value->type))
7340 return ira->codegen->invalid_inst_gen;
7341 }
7342
7343 heap::c_allocator.deallocate(elem_values, array_len);
7344 heap::c_allocator.deallocate(casted_fields, array_len);
7345
7346 return result_loc_inst;
7347}
7348
7349static Stage1AirInst *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, Scope *scope, AstNode *source_node,
7350 Stage1AirInst *struct_ptr, ZigType *actual_type, ZigType *wanted_type)
7351{
7352 Error err;
7353
7354 if (wanted_type->data.structure.resolve_status == ResolveStatusBeingInferred) {
7355 ir_add_error_node(ira, source_node, buf_sprintf("type coercion of anon struct literal to inferred struct"));
7356 return ira->codegen->invalid_inst_gen;
7357 }
7358
7359 if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusSizeKnown)))
7360 return ira->codegen->invalid_inst_gen;
7361
7362 size_t actual_field_count = wanted_type->data.structure.src_field_count;
7363 size_t instr_field_count = actual_type->data.structure.src_field_count;
7364
7365 bool need_comptime = ir_should_inline(ira->zir, scope)
7366 || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes;
7367 bool is_comptime = true;
7368
7369 // Determine if the struct_operand will be comptime.
7370 // Also emit compile errors for missing fields and duplicate fields.
7371 AstNode **field_assign_nodes = heap::c_allocator.allocate<AstNode *>(actual_field_count);
7372 ZigValue **field_values = heap::c_allocator.allocate<ZigValue *>(actual_field_count);
7373 Stage1AirInst **casted_fields = heap::c_allocator.allocate<Stage1AirInst *>(actual_field_count);
7374 Stage1AirInst *const_result = ir_const(ira, scope, source_node, wanted_type);
7375
7376 for (size_t i = 0; i < instr_field_count; i += 1) {
7377 TypeStructField *src_field = actual_type->data.structure.fields[i];
7378 TypeStructField *dst_field = find_struct_type_field(wanted_type, src_field->name);
7379 if (dst_field == nullptr) {
7380 ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("no field named '%s' in struct '%s'",
7381 buf_ptr(src_field->name), buf_ptr(&wanted_type->name)));
7382 if (wanted_type->data.structure.decl_node) {
7383 add_error_note(ira->codegen, msg, wanted_type->data.structure.decl_node,
7384 buf_sprintf("struct '%s' declared here", buf_ptr(&wanted_type->name)));
7385 }
7386 add_error_note(ira->codegen, msg, src_field->decl_node,
7387 buf_sprintf("field '%s' declared here", buf_ptr(src_field->name)));
7388 return ira->codegen->invalid_inst_gen;
7389 }
7390 if (dst_field->is_comptime) {
7391 ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("field '%s' in struct '%s' is comptime, it cannot be assigned",
7392 buf_ptr(src_field->name), buf_ptr(&wanted_type->name)));
7393 if (wanted_type->data.structure.decl_node) {
7394 add_error_note(ira->codegen, msg, wanted_type->data.structure.decl_node,
7395 buf_sprintf("struct '%s' declared here", buf_ptr(&wanted_type->name)));
7396 }
7397 add_error_note(ira->codegen, msg, src_field->decl_node,
7398 buf_sprintf("field '%s' declared here", buf_ptr(src_field->name)));
7399 return ira->codegen->invalid_inst_gen;
7400 }
7401
7402 src_assert(src_field->decl_node != nullptr, source_node);
7403 AstNode *existing_assign_node = field_assign_nodes[dst_field->src_index];
7404 if (existing_assign_node != nullptr) {
7405 ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("duplicate field"));
7406 add_error_note(ira->codegen, msg, existing_assign_node, buf_sprintf("other field here"));
7407 return ira->codegen->invalid_inst_gen;
7408 }
7409 field_assign_nodes[dst_field->src_index] = src_field->decl_node;
7410
7411 Stage1AirInst *field_ptr = ir_analyze_struct_field_ptr(ira, scope, source_node, src_field, struct_ptr,
7412 actual_type, false);
7413 if (type_is_invalid(field_ptr->value->type))
7414 return ira->codegen->invalid_inst_gen;
7415 Stage1AirInst *field_value = ir_get_deref(ira, scope, source_node, field_ptr, nullptr);
7416 if (type_is_invalid(field_value->value->type))
7417 return ira->codegen->invalid_inst_gen;
7418 Stage1AirInst *casted_value = ir_implicit_cast(ira, field_value, dst_field->type_entry);
7419 if (type_is_invalid(casted_value->value->type))
7420 return ira->codegen->invalid_inst_gen;
7421
7422 casted_fields[dst_field->src_index] = casted_value;
7423 if (need_comptime || instr_is_comptime(casted_value)) {
7424 ZigValue *field_val = ir_resolve_const(ira, casted_value, UndefOk);
7425 if (field_val == nullptr)
7426 return ira->codegen->invalid_inst_gen;
7427 field_val->parent.id = ConstParentIdStruct;
7428 field_val->parent.data.p_struct.struct_val = const_result->value;
7429 field_val->parent.data.p_struct.field_index = dst_field->src_index;
7430 field_values[dst_field->src_index] = field_val;
7431 if (field_val->type->id == ZigTypeIdUndefined && dst_field->type_entry->id != ZigTypeIdUndefined) {
7432 field_values[dst_field->src_index]->special = ConstValSpecialUndef;
7433 }
7434 } else {
7435 is_comptime = false;
7436 }
7437 }
7438
7439 bool any_missing = false;
7440 for (size_t i = 0; i < actual_field_count; i += 1) {
7441 if (field_assign_nodes[i] != nullptr) continue;
7442
7443 // look for a default field value
7444 TypeStructField *field = wanted_type->data.structure.fields[i];
7445 assert(!field->is_comptime); // field_assign_nodes[i] should be null for comptime fields
7446 memoize_field_init_val(ira->codegen, wanted_type, field);
7447 if (field->init_val == nullptr) {
7448 ir_add_error_node(ira, source_node,
7449 buf_sprintf("missing field: '%s'", buf_ptr(field->name)));
7450 any_missing = true;
7451 continue;
7452 }
7453 if (type_is_invalid(field->init_val->type))
7454 return ira->codegen->invalid_inst_gen;
7455 ZigValue *init_val_copy = ira->codegen->pass1_arena->create<ZigValue>();
7456 copy_const_val(ira->codegen, init_val_copy, field->init_val);
7457 init_val_copy->parent.id = ConstParentIdStruct;
7458 init_val_copy->parent.data.p_struct.struct_val = const_result->value;
7459 init_val_copy->parent.data.p_struct.field_index = i;
7460 field_values[i] = init_val_copy;
7461 casted_fields[i] = ir_const_move(ira, scope, source_node, init_val_copy);
7462 }
7463 if (any_missing)
7464 return ira->codegen->invalid_inst_gen;
7465
7466 if (is_comptime) {
7467 heap::c_allocator.deallocate(field_assign_nodes, actual_field_count);
7468 Stage1AirInst *const_result = ir_const(ira, scope, source_node, wanted_type);
7469 const_result->value->data.x_struct.fields = field_values;
7470 return const_result;
7471 }
7472
7473 Stage1AirInst *result_loc_inst = ir_resolve_result(ira, ira->suspend_source_instr, no_result_loc(),
7474 wanted_type, nullptr, true, true);
7475 if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
7476 return ira->codegen->invalid_inst_gen;
7477 }
7478
7479 for (size_t i = 0; i < actual_field_count; i += 1) {
7480 TypeStructField *field = wanted_type->data.structure.fields[i];
7481 if (field->is_comptime)
7482 continue;
7483
7484 Stage1AirInst *field_ptr = ir_analyze_struct_field_ptr(ira, scope, source_node, field, result_loc_inst, wanted_type, true);
7485 if (type_is_invalid(field_ptr->value->type))
7486 return ira->codegen->invalid_inst_gen;
7487 Stage1AirInst *store_ptr_inst = ir_analyze_store_ptr(ira, scope, source_node, field_ptr, casted_fields[i], true);
7488 if (type_is_invalid(store_ptr_inst->value->type))
7489 return ira->codegen->invalid_inst_gen;
7490 }
7491
7492 heap::c_allocator.deallocate(field_assign_nodes, actual_field_count);
7493 heap::c_allocator.deallocate(field_values, actual_field_count);
7494 heap::c_allocator.deallocate(casted_fields, actual_field_count);
7495
7496 return result_loc_inst;
7497}
7498
7499static Stage1AirInst *ir_analyze_struct_literal_to_union(IrAnalyze *ira, Scope *scope, AstNode *source_node,
7500 Stage1AirInst *struct_ptr, ZigType *struct_type, ZigType *union_type)
7501{
7502 Error err;
7503
7504 assert(struct_type->id == ZigTypeIdStruct);
7505 assert(union_type->id == ZigTypeIdUnion);
7506 assert(struct_type->data.structure.src_field_count == 1);
7507
7508 TypeStructField *only_field = struct_type->data.structure.fields[0];
7509
7510 if ((err = type_resolve(ira->codegen, union_type, ResolveStatusZeroBitsKnown)))
7511 return ira->codegen->invalid_inst_gen;
7512
7513 TypeUnionField *union_field = find_union_type_field(union_type, only_field->name);
7514 if (union_field == nullptr) {
7515 ir_add_error_node(ira, only_field->decl_node,
7516 buf_sprintf("no field named '%s' in union '%s'",
7517 buf_ptr(only_field->name), buf_ptr(&union_type->name)));
7518 return ira->codegen->invalid_inst_gen;
7519 }
7520
7521 ZigType *payload_type = resolve_union_field_type(ira->codegen, union_field);
7522 if (payload_type == nullptr)
7523 return ira->codegen->invalid_inst_gen;
7524
7525 Stage1AirInst *field_ptr = ir_analyze_struct_field_ptr(ira, scope, source_node, only_field, struct_ptr,
7526 struct_type, false);
7527 if (type_is_invalid(field_ptr->value->type))
7528 return ira->codegen->invalid_inst_gen;
7529 Stage1AirInst *field_value = ir_get_deref(ira, scope, source_node, field_ptr, nullptr);
7530 if (type_is_invalid(field_value->value->type))
7531 return ira->codegen->invalid_inst_gen;
7532
7533 Stage1AirInst *casted_value = ir_implicit_cast(ira, field_value, payload_type);
7534 if (type_is_invalid(casted_value->value->type))
7535 return ira->codegen->invalid_inst_gen;
7536
7537 if (instr_is_comptime(casted_value)) {
7538 ZigValue *val = ir_resolve_const(ira, casted_value, UndefBad);
7539 if (val == nullptr)
7540 return ira->codegen->invalid_inst_gen;
7541
7542 Stage1AirInst *result = ir_const(ira, scope, source_node, union_type);
7543 bigint_init_bigint(&result->value->data.x_union.tag, &union_field->enum_field->value);
7544 result->value->data.x_union.payload = val;
7545
7546 val->parent.id = ConstParentIdUnion;
7547 val->parent.data.p_union.union_val = result->value;
7548
7549 return result;
7550 }
7551
7552 Stage1AirInst *result_loc_inst = ir_resolve_result(ira, ira->suspend_source_instr, no_result_loc(),
7553 union_type, nullptr, true, true);
7554 if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
7555 return ira->codegen->invalid_inst_gen;
7556 }
7557
7558 Stage1AirInst *payload_ptr = ir_analyze_container_field_ptr(ira, only_field->name,
7559 scope, source_node, result_loc_inst, source_node, union_type, true);
7560 if (type_is_invalid(payload_ptr->value->type))
7561 return ira->codegen->invalid_inst_gen;
7562
7563 Stage1AirInst *store_ptr_inst = ir_analyze_store_ptr(ira, scope, source_node, payload_ptr, casted_value, false);
7564 if (type_is_invalid(store_ptr_inst->value->type))
7565 return ira->codegen->invalid_inst_gen;
7566
7567 return result_loc_inst;
7568}
7569
7570// Add a compile error and return ErrorSemanticAnalyzeFail if the pointer alignment does not work,
7571// otherwise return ErrorNone. Does not emit any instructions.
7572// Assumes that the pointer types have element types with the same ABI alignment. Avoids resolving the
7573// pointer types' alignments if both of the pointer types are ABI aligned.
7574static Error ir_cast_ptr_align(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *dest_ptr_type,
7575 ZigType *src_ptr_type, AstNode *src_source_node)
7576{
7577 Error err;
7578
7579 src_assert(dest_ptr_type->id == ZigTypeIdPointer, source_node);
7580 src_assert(src_ptr_type->id == ZigTypeIdPointer, source_node);
7581
7582 if (dest_ptr_type->data.pointer.explicit_alignment == 0 &&
7583 src_ptr_type->data.pointer.explicit_alignment == 0)
7584 {
7585 return ErrorNone;
7586 }
7587
7588 if ((err = type_resolve(ira->codegen, dest_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
7589 return ErrorSemanticAnalyzeFail;
7590
7591 if ((err = type_resolve(ira->codegen, src_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
7592 return ErrorSemanticAnalyzeFail;
7593
7594 uint32_t wanted_align = get_ptr_align(ira->codegen, dest_ptr_type);
7595 uint32_t actual_align = get_ptr_align(ira->codegen, src_ptr_type);
7596 if (wanted_align > actual_align) {
7597 ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("cast increases pointer alignment"));
7598 add_error_note(ira->codegen, msg, src_source_node,
7599 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_ptr_type->name), actual_align));
7600 add_error_note(ira->codegen, msg, source_node,
7601 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&dest_ptr_type->name), wanted_align));
7602 return ErrorSemanticAnalyzeFail;
7603 }
7604
7605 return ErrorNone;
7606}
7607
7608static Stage1AirInst *ir_analyze_struct_value_field_value(IrAnalyze *ira, Scope *scope, AstNode *source_node,
7609 Stage1AirInst *struct_operand, TypeStructField *field)
7610{
7611 Stage1AirInst *struct_ptr = ir_get_ref(ira, scope, source_node, struct_operand, true, false);
7612 if (type_is_invalid(struct_ptr->value->type))
7613 return ira->codegen->invalid_inst_gen;
7614 Stage1AirInst *field_ptr = ir_analyze_struct_field_ptr(ira, scope, source_node, field, struct_ptr,
7615 struct_operand->value->type, false);
7616 if (type_is_invalid(field_ptr->value->type))
7617 return ira->codegen->invalid_inst_gen;
7618 return ir_get_deref(ira, scope, source_node, field_ptr, nullptr);
7619}
7620
7621static Stage1AirInst *ir_analyze_optional_value_payload_value(IrAnalyze *ira, Scope *scope, AstNode *source_node,
7622 Stage1AirInst *optional_operand, bool safety_check_on)
7623{
7624 Stage1AirInst *opt_ptr = ir_get_ref(ira, scope, source_node, optional_operand, true, false);
7625 Stage1AirInst *payload_ptr = ir_analyze_unwrap_optional_payload(ira, scope, source_node, opt_ptr,
7626 safety_check_on, false);
7627 return ir_get_deref(ira, scope, source_node, payload_ptr, nullptr);
7628}
7629
7630static Stage1AirInst *ir_analyze_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node,
7631 ZigType *wanted_type, Stage1AirInst *value)
7632{
7633 Error err;
7634 ZigType *actual_type = value->value->type;
7635
7636 if (type_is_invalid(wanted_type) || type_is_invalid(actual_type)) {
7637 return ira->codegen->invalid_inst_gen;
7638 }
7639
7640 // This means the wanted type is anything.
7641 if (wanted_type == ira->codegen->builtin_types.entry_anytype) {
7642 return value;
7643 }
7644
7645 // perfect match or non-const to const
7646 ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type, actual_type,
7647 source_node, false);
7648 if (const_cast_result.id == ConstCastResultIdInvalid)
7649 return ira->codegen->invalid_inst_gen;
7650 if (const_cast_result.id == ConstCastResultIdOk) {
7651 return ir_resolve_cast(ira, scope, source_node, value, wanted_type, CastOpNoop);
7652 }
7653
7654 if (const_cast_result.id == ConstCastResultIdFnCC) {
7655 src_assert(value->value->type->id == ZigTypeIdFn, source_node);
7656 // ConstCastResultIdFnCC is guaranteed to be the last one reported, meaning everything else is ok.
7657 if (wanted_type->data.fn.fn_type_id.cc == CallingConventionAsync &&
7658 actual_type->data.fn.fn_type_id.cc == CallingConventionUnspecified)
7659 {
7660 src_assert(value->value->data.x_ptr.special == ConstPtrSpecialFunction, source_node);
7661 ZigFn *fn = value->value->data.x_ptr.data.fn.fn_entry;
7662 if (fn->inferred_async_node == nullptr) {
7663 fn->inferred_async_node = source_node;
7664 }
7665 return ir_resolve_cast(ira, scope, source_node, value, wanted_type, CastOpNoop);
7666 }
7667 }
7668
7669 // cast from T to ?T
7670 // note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism
7671 if (wanted_type->id == ZigTypeIdOptional) {
7672 ZigType *wanted_child_type = wanted_type->data.maybe.child_type;
7673 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
7674 false).id == ConstCastResultIdOk)
7675 {
7676 return ir_analyze_optional_wrap(ira, scope, source_node, value, wanted_type, nullptr);
7677 } else if (actual_type->id == ZigTypeIdComptimeInt ||
7678 actual_type->id == ZigTypeIdComptimeFloat)
7679 {
7680 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
7681 return ir_analyze_optional_wrap(ira, scope, source_node, value, wanted_type, nullptr);
7682 } else {
7683 return ira->codegen->invalid_inst_gen;
7684 }
7685 } else if (
7686 wanted_child_type->id == ZigTypeIdPointer &&
7687 wanted_child_type->data.pointer.ptr_len == PtrLenUnknown &&
7688 actual_type->id == ZigTypeIdPointer &&
7689 actual_type->data.pointer.ptr_len == PtrLenSingle &&
7690 actual_type->data.pointer.child_type->id == ZigTypeIdArray)
7691 {
7692 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
7693 return ira->codegen->invalid_inst_gen;
7694 if ((err = type_resolve(ira->codegen, wanted_child_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
7695 return ira->codegen->invalid_inst_gen;
7696 if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_child_type) &&
7697 types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type,
7698 actual_type->data.pointer.child_type->data.array.child_type, source_node,
7699 !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk)
7700 {
7701 Stage1AirInst *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, scope, source_node, value,
7702 wanted_child_type);
7703 if (type_is_invalid(cast1->value->type))
7704 return ira->codegen->invalid_inst_gen;
7705 return ir_analyze_optional_wrap(ira, scope, source_node, cast1, wanted_type, nullptr);
7706 }
7707 }
7708 }
7709
7710 // T to E!T
7711 if (wanted_type->id == ZigTypeIdErrorUnion) {
7712 if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,
7713 source_node, false).id == ConstCastResultIdOk)
7714 {
7715 return ir_analyze_err_wrap_payload(ira, scope, source_node, value, wanted_type, nullptr);
7716 } else if (actual_type->id == ZigTypeIdComptimeInt ||
7717 actual_type->id == ZigTypeIdComptimeFloat)
7718 {
7719 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {
7720 return ir_analyze_err_wrap_payload(ira, scope, source_node, value, wanted_type, nullptr);
7721 } else {
7722 return ira->codegen->invalid_inst_gen;
7723 }
7724 }
7725 }
7726
7727 // cast from T to E!?T
7728 if (wanted_type->id == ZigTypeIdErrorUnion &&
7729 wanted_type->data.error_union.payload_type->id == ZigTypeIdOptional &&
7730 actual_type->id != ZigTypeIdOptional)
7731 {
7732 ZigType *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type;
7733 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, false).id == ConstCastResultIdOk ||
7734 actual_type->id == ZigTypeIdNull ||
7735 actual_type->id == ZigTypeIdComptimeInt ||
7736 actual_type->id == ZigTypeIdComptimeFloat)
7737 {
7738 Stage1AirInst *cast1 = ir_analyze_cast(ira, scope, source_node, wanted_type->data.error_union.payload_type, value);
7739 if (type_is_invalid(cast1->value->type))
7740 return ira->codegen->invalid_inst_gen;
7741
7742 Stage1AirInst *cast2 = ir_analyze_cast(ira, scope, source_node, wanted_type, cast1);
7743 if (type_is_invalid(cast2->value->type))
7744 return ira->codegen->invalid_inst_gen;
7745
7746 return cast2;
7747 }
7748 }
7749
7750
7751 // cast from comptime-known number to another number type
7752 if (instr_is_comptime(value) &&
7753 (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt ||
7754 actual_type->id == ZigTypeIdFloat || actual_type->id == ZigTypeIdComptimeFloat) &&
7755 (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt ||
7756 wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat))
7757 {
7758 if (value->value->special == ConstValSpecialUndef) {
7759 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
7760 result->value->special = ConstValSpecialUndef;
7761 return result;
7762 }
7763 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
7764 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {
7765 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
7766 if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) {
7767 copy_const_val(ira->codegen, result->value, value->value);
7768 result->value->type = wanted_type;
7769 } else {
7770 float_init_bigint(&result->value->data.x_bigint, value->value);
7771 }
7772 return result;
7773 } else if (wanted_type->id == ZigTypeIdComptimeFloat || wanted_type->id == ZigTypeIdFloat) {
7774 Stage1AirInst *result = ir_const(ira, scope, source_node, wanted_type);
7775 if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) {
7776 BigFloat bf;
7777 bigfloat_init_bigint(&bf, &value->value->data.x_bigint);
7778 float_init_bigfloat(result->value, &bf);
7779 } else {
7780 float_init_float(result->value, value->value);
7781 }
7782 return result;
7783 }
7784 zig_unreachable();
7785 } else {
7786 return ira->codegen->invalid_inst_gen;
7787 }
7788 }
7789
7790 // widening conversion
7791 if (wanted_type->id == ZigTypeIdInt &&
7792 actual_type->id == ZigTypeIdInt &&
7793 wanted_type->data.integral.is_signed == actual_type->data.integral.is_signed &&
7794 wanted_type->data.integral.bit_count >= actual_type->data.integral.bit_count)
7795 {
7796 return ir_analyze_widen_or_shorten(ira, scope, source_node, value, wanted_type);
7797 }
7798
7799 // small enough unsigned ints can get casted to large enough signed ints
7800 if (wanted_type->id == ZigTypeIdInt && wanted_type->data.integral.is_signed &&
7801 actual_type->id == ZigTypeIdInt && !actual_type->data.integral.is_signed &&
7802 wanted_type->data.integral.bit_count > actual_type->data.integral.bit_count)
7803 {
7804 return ir_analyze_widen_or_shorten(ira, scope, source_node, value, wanted_type);
7805 }
7806
7807 // float widening conversion
7808 if (wanted_type->id == ZigTypeIdFloat &&
7809 actual_type->id == ZigTypeIdFloat &&
7810 wanted_type->data.floating.bit_count >= actual_type->data.floating.bit_count)
7811 {
7812 return ir_analyze_widen_or_shorten(ira, scope, source_node, value, wanted_type);
7813 }
7814
7815 // *[N]T to ?[]T
7816 if (wanted_type->id == ZigTypeIdOptional &&
7817 is_slice(wanted_type->data.maybe.child_type) &&
7818 actual_type->id == ZigTypeIdPointer &&
7819 actual_type->data.pointer.ptr_len == PtrLenSingle &&
7820 actual_type->data.pointer.child_type->id == ZigTypeIdArray)
7821 {
7822 Stage1AirInst *cast1 = ir_analyze_cast(ira, scope, source_node, wanted_type->data.maybe.child_type, value);
7823 if (type_is_invalid(cast1->value->type))
7824 return ira->codegen->invalid_inst_gen;
7825
7826 Stage1AirInst *cast2 = ir_analyze_cast(ira, scope, source_node, wanted_type, cast1);
7827 if (type_is_invalid(cast2->value->type))
7828 return ira->codegen->invalid_inst_gen;
7829
7830 return cast2;
7831 }
7832
7833 // *[N]T to [*]T and [*c]T
7834 if (wanted_type->id == ZigTypeIdPointer &&
7835 (wanted_type->data.pointer.ptr_len == PtrLenUnknown || wanted_type->data.pointer.ptr_len == PtrLenC) &&
7836 actual_type->id == ZigTypeIdPointer &&
7837 actual_type->data.pointer.ptr_len == PtrLenSingle &&
7838 actual_type->data.pointer.child_type->id == ZigTypeIdArray &&
7839 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
7840 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
7841 {
7842 ZigType *actual_array_type = actual_type->data.pointer.child_type;
7843 if (wanted_type->data.pointer.sentinel == nullptr ||
7844 (actual_array_type->data.array.sentinel != nullptr &&
7845 const_values_equal(ira->codegen, wanted_type->data.pointer.sentinel,
7846 actual_array_type->data.array.sentinel)))
7847 {
7848 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
7849 return ira->codegen->invalid_inst_gen;
7850 if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
7851 return ira->codegen->invalid_inst_gen;
7852 if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type) &&
7853 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
7854 actual_type->data.pointer.child_type->data.array.child_type, source_node,
7855 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
7856 {
7857 return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, scope, source_node, value, wanted_type);
7858 }
7859 }
7860 }
7861
7862 // *[N]T to []T
7863 // *[N]T to E![]T
7864 if ((is_slice(wanted_type) ||
7865 (wanted_type->id == ZigTypeIdErrorUnion &&
7866 is_slice(wanted_type->data.error_union.payload_type))) &&
7867 actual_type->id == ZigTypeIdPointer &&
7868 actual_type->data.pointer.ptr_len == PtrLenSingle &&
7869 actual_type->data.pointer.child_type->id == ZigTypeIdArray)
7870 {
7871 ZigType *slice_type = (wanted_type->id == ZigTypeIdErrorUnion) ?
7872 wanted_type->data.error_union.payload_type : wanted_type;
7873 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
7874 assert(slice_ptr_type->id == ZigTypeIdPointer);
7875 ZigType *array_type = actual_type->data.pointer.child_type;
7876 bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0
7877 || !actual_type->data.pointer.is_const);
7878
7879 if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
7880 array_type->data.array.child_type, source_node,
7881 !slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk &&
7882 (slice_ptr_type->data.pointer.sentinel == nullptr ||
7883 (array_type->data.array.sentinel != nullptr &&
7884 const_values_equal(ira->codegen, array_type->data.array.sentinel,
7885 slice_ptr_type->data.pointer.sentinel))))
7886 {
7887 if (!const_ok) {
7888 ErrorMsg *msg = ir_add_error_node(ira, source_node,
7889 buf_sprintf("cannot cast pointer to array literal to slice type '%s'",
7890 buf_ptr(&wanted_type->name)));
7891 add_error_note(ira->codegen, msg, source_node,
7892 buf_sprintf("cast discards const qualifier"));
7893 return ira->codegen->invalid_inst_gen;
7894 }
7895 // If the pointers both have ABI align, it works.
7896 // Or if the array length is 0, alignment doesn't matter.
7897 bool ok_align = array_type->data.array.len == 0 ||
7898 (slice_ptr_type->data.pointer.explicit_alignment == 0 &&
7899 actual_type->data.pointer.explicit_alignment == 0);
7900 if (!ok_align) {
7901 // If either one has non ABI align, we have to resolve them both
7902 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type,
7903 ResolveStatusAlignmentKnown)))
7904 {
7905 return ira->codegen->invalid_inst_gen;
7906 }
7907 if ((err = type_resolve(ira->codegen, slice_ptr_type->data.pointer.child_type,
7908 ResolveStatusAlignmentKnown)))
7909 {
7910 return ira->codegen->invalid_inst_gen;
7911 }
7912 ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type);
7913 }
7914 if (ok_align) {
7915 if (wanted_type->id == ZigTypeIdErrorUnion) {
7916 Stage1AirInst *cast1 = ir_analyze_cast(ira, scope, source_node, slice_type, value);
7917 if (type_is_invalid(cast1->value->type))
7918 return ira->codegen->invalid_inst_gen;
7919
7920 Stage1AirInst *cast2 = ir_analyze_cast(ira, scope, source_node, wanted_type, cast1);
7921 if (type_is_invalid(cast2->value->type))
7922 return ira->codegen->invalid_inst_gen;
7923
7924 return cast2;
7925 } else {
7926 return ir_resolve_ptr_of_array_to_slice(ira, scope, source_node, value, slice_type, nullptr);
7927 }
7928 }
7929 }
7930 }
7931
7932 // @Vector(N,T1) to @Vector(N,T2)
7933 if (actual_type->id == ZigTypeIdVector && wanted_type->id == ZigTypeIdVector &&
7934 actual_type->data.vector.len == wanted_type->data.vector.len)
7935 {
7936 ZigType *scalar_actual_type = actual_type->data.vector.elem_type;
7937 ZigType *scalar_wanted_type = wanted_type->data.vector.elem_type;
7938
7939 // widening conversion
7940 if (scalar_wanted_type->id == ZigTypeIdInt &&
7941 scalar_actual_type->id == ZigTypeIdInt &&
7942 scalar_wanted_type->data.integral.is_signed == scalar_actual_type->data.integral.is_signed &&
7943 scalar_wanted_type->data.integral.bit_count >= scalar_actual_type->data.integral.bit_count)
7944 {
7945 return ir_analyze_widen_or_shorten(ira, scope, source_node, value, wanted_type);
7946 }
7947
7948 // small enough unsigned ints can get casted to large enough signed ints
7949 if (scalar_wanted_type->id == ZigTypeIdInt && scalar_wanted_type->data.integral.is_signed &&
7950 scalar_actual_type->id == ZigTypeIdInt && !scalar_actual_type->data.integral.is_signed &&
7951 scalar_wanted_type->data.integral.bit_count > scalar_actual_type->data.integral.bit_count)
7952 {
7953 return ir_analyze_widen_or_shorten(ira, scope, source_node, value, wanted_type);
7954 }
7955
7956 // float widening conversion
7957 if (scalar_wanted_type->id == ZigTypeIdFloat &&
7958 scalar_actual_type->id == ZigTypeIdFloat &&
7959 scalar_wanted_type->data.floating.bit_count >= scalar_actual_type->data.floating.bit_count)
7960 {
7961 return ir_analyze_widen_or_shorten(ira, scope, source_node, value, wanted_type);
7962 }
7963 }
7964
7965 // *@Frame(func) to anyframe->T or anyframe
7966 // *@Frame(func) to ?anyframe->T or ?anyframe
7967 // *@Frame(func) to E!anyframe->T or E!anyframe
7968 if (actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle &&
7969 !actual_type->data.pointer.is_const &&
7970 actual_type->data.pointer.child_type->id == ZigTypeIdFnFrame)
7971 {
7972 ZigType *anyframe_type;
7973 if (wanted_type->id == ZigTypeIdAnyFrame) {
7974 anyframe_type = wanted_type;
7975 } else if (wanted_type->id == ZigTypeIdOptional &&
7976 wanted_type->data.maybe.child_type->id == ZigTypeIdAnyFrame)
7977 {
7978 anyframe_type = wanted_type->data.maybe.child_type;
7979 } else if (wanted_type->id == ZigTypeIdErrorUnion &&
7980 wanted_type->data.error_union.payload_type->id == ZigTypeIdAnyFrame)
7981 {
7982 anyframe_type = wanted_type->data.error_union.payload_type;
7983 } else {
7984 anyframe_type = nullptr;
7985 }
7986 if (anyframe_type != nullptr) {
7987 bool ok = true;
7988 if (anyframe_type->data.any_frame.result_type != nullptr) {
7989 ZigFn *fn = actual_type->data.pointer.child_type->data.frame.fn;
7990 ZigType *fn_return_type = fn->type_entry->data.fn.fn_type_id.return_type;
7991 if (anyframe_type->data.any_frame.result_type != fn_return_type) {
7992 ok = false;
7993 }
7994 }
7995 if (ok) {
7996 Stage1AirInst *cast1 = ir_analyze_frame_ptr_to_anyframe(ira, scope, source_node, value, anyframe_type);
7997 if (anyframe_type == wanted_type)
7998 return cast1;
7999 return ir_analyze_cast(ira, scope, source_node, wanted_type, cast1);
8000 }
8001 }
8002 }
8003
8004 // anyframe->T to anyframe
8005 if (actual_type->id == ZigTypeIdAnyFrame && actual_type->data.any_frame.result_type != nullptr &&
8006 wanted_type->id == ZigTypeIdAnyFrame && wanted_type->data.any_frame.result_type == nullptr)
8007 {
8008 return ir_analyze_anyframe_to_anyframe(ira, scope, source_node, value, wanted_type);
8009 }
8010
8011 // cast from null literal to maybe type
8012 if (wanted_type->id == ZigTypeIdOptional &&
8013 actual_type->id == ZigTypeIdNull)
8014 {
8015 return ir_analyze_null_to_maybe(ira, scope, source_node, value, wanted_type);
8016 }
8017
8018 // cast from null literal to C pointer
8019 if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC &&
8020 actual_type->id == ZigTypeIdNull)
8021 {
8022 return ir_analyze_null_to_c_pointer(ira, scope, source_node, value, wanted_type);
8023 }
8024
8025 // cast from E to E!T
8026 if (wanted_type->id == ZigTypeIdErrorUnion &&
8027 actual_type->id == ZigTypeIdErrorSet)
8028 {
8029 return ir_analyze_err_wrap_code(ira, scope, source_node, value, wanted_type, nullptr);
8030 }
8031
8032 // cast from typed number to integer or float literal.
8033 // works when the number is known at compile time
8034 if (instr_is_comptime(value) &&
8035 ((actual_type->id == ZigTypeIdInt && wanted_type->id == ZigTypeIdComptimeInt) ||
8036 (actual_type->id == ZigTypeIdFloat && wanted_type->id == ZigTypeIdComptimeFloat)))
8037 {
8038 return ir_analyze_number_to_literal(ira, scope, source_node, value, wanted_type);
8039 }
8040
8041 // cast from enum literal to enum with matching field name
8042 if (actual_type->id == ZigTypeIdEnumLiteral && wanted_type->id == ZigTypeIdEnum)
8043 {
8044 return ir_analyze_enum_literal(ira, scope, source_node, value, wanted_type);
8045 }
8046
8047 // cast from enum literal to optional enum
8048 if (actual_type->id == ZigTypeIdEnumLiteral &&
8049 (wanted_type->id == ZigTypeIdOptional && wanted_type->data.maybe.child_type->id == ZigTypeIdEnum))
8050 {
8051 Stage1AirInst *result = ir_analyze_enum_literal(ira, scope, source_node, value, wanted_type->data.maybe.child_type);
8052 if (type_is_invalid(result->value->type))
8053 return result;
8054
8055 return ir_analyze_optional_wrap(ira, scope, source_node, value, wanted_type, nullptr);
8056 }
8057
8058 // cast from enum literal to error union when payload is an enum
8059 if (actual_type->id == ZigTypeIdEnumLiteral &&
8060 (wanted_type->id == ZigTypeIdErrorUnion && wanted_type->data.error_union.payload_type->id == ZigTypeIdEnum))
8061 {
8062 Stage1AirInst *result = ir_analyze_enum_literal(ira, scope, source_node, value, wanted_type->data.error_union.payload_type);
8063 if (type_is_invalid(result->value->type))
8064 return result;
8065
8066 return ir_analyze_err_wrap_payload(ira, scope, source_node, value, wanted_type, nullptr);
8067 }
8068
8069 // cast from union to the enum type of the union
8070 if (actual_type->id == ZigTypeIdUnion && wanted_type->id == ZigTypeIdEnum) {
8071 if ((err = type_resolve(ira->codegen, actual_type, ResolveStatusZeroBitsKnown)))
8072 return ira->codegen->invalid_inst_gen;
8073
8074 if (actual_type->data.unionation.tag_type == wanted_type) {
8075 return ir_analyze_union_to_tag(ira, scope, source_node, value, wanted_type);
8076 }
8077 }
8078
8079 // enum to union which has the enum as the tag type, or
8080 // enum literal to union which has a matching enum as the tag type
8081 if (is_tagged_union(wanted_type) && (actual_type->id == ZigTypeIdEnum ||
8082 actual_type->id == ZigTypeIdEnumLiteral))
8083 {
8084 return ir_analyze_enum_to_union(ira, scope, source_node, value, wanted_type);
8085 }
8086
8087 // cast from *T to *[1]T
8088 if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle &&
8089 actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle)
8090 {
8091 ZigType *array_type = wanted_type->data.pointer.child_type;
8092 if (array_type->id == ZigTypeIdArray && array_type->data.array.len == 1 &&
8093 types_match_const_cast_only(ira, array_type->data.array.child_type,
8094 actual_type->data.pointer.child_type, source_node,
8095 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk &&
8096 // `types_match_const_cast_only` only gets info for child_types
8097 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
8098 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
8099 {
8100 if ((err = ir_cast_ptr_align(ira, scope, source_node, wanted_type, actual_type, value->source_node)))
8101 return ira->codegen->invalid_inst_gen;
8102
8103 return ir_analyze_ptr_to_array(ira, scope, source_node, value, wanted_type);
8104 }
8105 }
8106
8107 // [:x]T to [*:x]T
8108 // [:x]T to [*c]T
8109 if (wanted_type->id == ZigTypeIdPointer && is_slice(actual_type) &&
8110 ((wanted_type->data.pointer.ptr_len == PtrLenUnknown && wanted_type->data.pointer.sentinel != nullptr) ||
8111 wanted_type->data.pointer.ptr_len == PtrLenC))
8112 {
8113 ZigType *slice_ptr_type = resolve_struct_field_type(ira->codegen,
8114 actual_type->data.structure.fields[slice_ptr_index]);
8115 if (types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
8116 slice_ptr_type->data.pointer.child_type, source_node,
8117 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk &&
8118 (slice_ptr_type->data.pointer.sentinel != nullptr &&
8119 (wanted_type->data.pointer.ptr_len == PtrLenC ||
8120 const_values_equal(ira->codegen, wanted_type->data.pointer.sentinel,
8121 slice_ptr_type->data.pointer.sentinel))))
8122 {
8123 TypeStructField *ptr_field = actual_type->data.structure.fields[slice_ptr_index];
8124 Stage1AirInst *slice_ptr = ir_analyze_struct_value_field_value(ira, scope, source_node, value, ptr_field);
8125 return ir_implicit_cast2(ira, scope, source_node, slice_ptr, wanted_type);
8126 }
8127 }
8128
8129 // cast from *T and [*]T to *anyopaque and ?*anyopaque
8130 // but don't do it if the actual type is a double pointer
8131 if (is_pointery_and_elem_is_not_pointery(actual_type)) {
8132 ZigType *dest_ptr_type = nullptr;
8133 if (wanted_type->id == ZigTypeIdPointer &&
8134 actual_type->id != ZigTypeIdOptional &&
8135 wanted_type->data.pointer.child_type == ira->codegen->builtin_types.entry_anyopaque)
8136 {
8137 dest_ptr_type = wanted_type;
8138 } else if (wanted_type->id == ZigTypeIdOptional &&
8139 wanted_type->data.maybe.child_type->id == ZigTypeIdPointer &&
8140 wanted_type->data.maybe.child_type->data.pointer.child_type == ira->codegen->builtin_types.entry_anyopaque)
8141 {
8142 dest_ptr_type = wanted_type->data.maybe.child_type;
8143 }
8144 if (dest_ptr_type != nullptr) {
8145 return ir_analyze_ptr_cast(ira, scope, source_node, value, source_node,
8146 wanted_type, source_node, true, false);
8147 }
8148 }
8149
8150 // cast from T to *T where T is zero bits
8151 if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle &&
8152 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
8153 actual_type, source_node, !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
8154 {
8155 bool has_bits;
8156 if ((err = type_has_bits2(ira->codegen, actual_type, &has_bits)))
8157 return ira->codegen->invalid_inst_gen;
8158 if (!has_bits) {
8159 return ir_get_ref(ira, scope, source_node, value, false, false);
8160 }
8161 }
8162
8163 // cast from @Vector(N, T) to [N]T
8164 if (wanted_type->id == ZigTypeIdArray && actual_type->id == ZigTypeIdVector &&
8165 wanted_type->data.array.len == actual_type->data.vector.len &&
8166 types_match_const_cast_only(ira, wanted_type->data.array.child_type,
8167 actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
8168 {
8169 return ir_analyze_vector_to_array(ira, scope, source_node, value, wanted_type, nullptr);
8170 }
8171
8172 // cast from [N]T to @Vector(N, T)
8173 if (actual_type->id == ZigTypeIdArray && wanted_type->id == ZigTypeIdVector &&
8174 actual_type->data.array.len == wanted_type->data.vector.len &&
8175 types_match_const_cast_only(ira, actual_type->data.array.child_type,
8176 wanted_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
8177 {
8178 return ir_analyze_array_to_vector(ira, scope, source_node, value, wanted_type);
8179 }
8180
8181 // casting between C pointers and normal pointers
8182 if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer &&
8183 (wanted_type->data.pointer.ptr_len == PtrLenC || actual_type->data.pointer.ptr_len == PtrLenC) &&
8184 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
8185 actual_type->data.pointer.child_type, source_node,
8186 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
8187 {
8188 return ir_analyze_ptr_cast(ira, scope, source_node, value, source_node,
8189 wanted_type, source_node, true, false);
8190 }
8191
8192 // cast from integer to C pointer
8193 if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC &&
8194 (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt))
8195 {
8196 return ir_analyze_int_to_c_ptr(ira, scope, source_node, value, wanted_type);
8197 }
8198
8199 // cast from inferred struct type to array, union, or struct
8200 if (is_anon_container(actual_type)) {
8201 const bool is_array_init =
8202 actual_type->data.structure.special == StructSpecialInferredTuple;
8203 const uint32_t field_count = actual_type->data.structure.src_field_count;
8204
8205 if (wanted_type->id == ZigTypeIdArray && (is_array_init || field_count == 0) &&
8206 wanted_type->data.array.len == field_count)
8207 {
8208 Stage1AirInst *struct_ptr = ir_get_ref(ira, scope, source_node, value, true, false);
8209 if (type_is_invalid(struct_ptr->value->type))
8210 return ira->codegen->invalid_inst_gen;
8211
8212 Stage1AirInst *ptr = ir_analyze_struct_literal_to_array(ira, scope, source_node, struct_ptr, actual_type, wanted_type);
8213 if (ptr->value->type->id != ZigTypeIdPointer)
8214 return ptr;
8215 return ir_get_deref(ira, scope, source_node, ptr, nullptr);
8216 } else if (wanted_type->id == ZigTypeIdStruct && !is_slice(wanted_type) &&
8217 (!is_array_init || field_count == 0))
8218 {
8219 Stage1AirInst *struct_ptr = ir_get_ref(ira, scope, source_node, value, true, false);
8220 if (type_is_invalid(struct_ptr->value->type))
8221 return ira->codegen->invalid_inst_gen;
8222
8223 Stage1AirInst *ptr = ir_analyze_struct_literal_to_struct(ira, scope, source_node, struct_ptr, actual_type, wanted_type);
8224 if (ptr->value->type->id != ZigTypeIdPointer)
8225 return ptr;
8226 return ir_get_deref(ira, scope, source_node, ptr, nullptr);
8227 } else if (wanted_type->id == ZigTypeIdUnion && !is_array_init && field_count == 1) {
8228 Stage1AirInst *struct_ptr = ir_get_ref(ira, scope, source_node, value, true, false);
8229 if (type_is_invalid(struct_ptr->value->type))
8230 return ira->codegen->invalid_inst_gen;
8231
8232 Stage1AirInst *ptr = ir_analyze_struct_literal_to_union(ira, scope, source_node, struct_ptr, actual_type, wanted_type);
8233 if (ptr->value->type->id != ZigTypeIdPointer)
8234 return ptr;
8235 return ir_get_deref(ira, scope, source_node, ptr, nullptr);
8236 }
8237 }
8238
8239 // cast from pointer to inferred struct type to pointer to array, union, or struct
8240 if (actual_type->id == ZigTypeIdPointer && is_anon_container(actual_type->data.pointer.child_type)) {
8241 ZigType *anon_type = actual_type->data.pointer.child_type;
8242 const bool is_array_init =
8243 anon_type->data.structure.special == StructSpecialInferredTuple;
8244 const uint32_t field_count = anon_type->data.structure.src_field_count;
8245
8246 if (wanted_type->id == ZigTypeIdPointer &&
8247 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
8248 {
8249 ZigType *wanted_child = wanted_type->data.pointer.child_type;
8250 bool const_ok = (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const);
8251 if (wanted_child->id == ZigTypeIdArray && (is_array_init || field_count == 0) &&
8252 wanted_child->data.array.len == field_count)
8253 {
8254 if (!const_ok && field_count != 0) {
8255 ErrorMsg *msg = ir_add_error_node(ira, source_node,
8256 buf_sprintf("cannot cast pointer to array literal to '%s'",
8257 buf_ptr(&wanted_type->name)));
8258 add_error_note(ira->codegen, msg, source_node,
8259 buf_sprintf("cast discards const qualifier"));
8260 return ira->codegen->invalid_inst_gen;
8261 }
8262 Stage1AirInst *res = ir_analyze_struct_literal_to_array(ira, scope, source_node, value, anon_type, wanted_child);
8263 if (res->value->type->id == ZigTypeIdPointer)
8264 return res;
8265 return ir_get_ref(ira, scope, source_node, res, actual_type->data.pointer.is_const, actual_type->data.pointer.is_volatile);
8266 } else if (wanted_child->id == ZigTypeIdStruct && !is_slice(wanted_type) &&
8267 (!is_array_init || field_count == 0) && const_ok)
8268 {
8269 Stage1AirInst *res = ir_analyze_struct_literal_to_struct(ira, scope, source_node, value, anon_type, wanted_child);
8270 if (res->value->type->id == ZigTypeIdPointer)
8271 return res;
8272 return ir_get_ref(ira, scope, source_node, res, actual_type->data.pointer.is_const, actual_type->data.pointer.is_volatile);
8273 } else if (wanted_child->id == ZigTypeIdUnion && !is_array_init && field_count == 1 && const_ok) {
8274 Stage1AirInst *res = ir_analyze_struct_literal_to_union(ira, scope, source_node, value, anon_type, wanted_child);
8275 if (res->value->type->id == ZigTypeIdPointer)
8276 return res;
8277 return ir_get_ref(ira, scope, source_node, res, actual_type->data.pointer.is_const, actual_type->data.pointer.is_volatile);
8278 }
8279 } else if (is_slice(wanted_type) && (is_array_init || field_count == 0)) {
8280 ZigType *slice_type = wanted_type->data.structure.fields[slice_ptr_index]->type_entry;
8281 if ((!actual_type->data.pointer.is_const || slice_type->data.pointer.is_const || field_count == 0) &&
8282 (!actual_type->data.pointer.is_volatile || slice_type->data.pointer.is_volatile))
8283 {
8284 ZigType *slice_child_type = slice_type->data.pointer.child_type;
8285 ZigType *slice_array_type = get_array_type(ira->codegen, slice_child_type, field_count, nullptr);
8286 Stage1AirInst *res = ir_analyze_struct_literal_to_array(ira, scope, source_node, value, anon_type, slice_array_type);
8287 if (type_is_invalid(res->value->type))
8288 return ira->codegen->invalid_inst_gen;
8289 if (res->value->type->id != ZigTypeIdPointer)
8290 res = ir_get_ref(ira, scope, source_node, res, actual_type->data.pointer.is_const, actual_type->data.pointer.is_volatile);
8291
8292 return ir_resolve_ptr_of_array_to_slice(ira, scope, source_node, res, wanted_type, nullptr);
8293 } else if (!slice_type->data.pointer.is_const && actual_type->data.pointer.is_const && field_count != 0) {
8294 ErrorMsg *msg = ir_add_error_node(ira, source_node,
8295 buf_sprintf("cannot cast pointer to array literal to slice type '%s'",
8296 buf_ptr(&wanted_type->name)));
8297 add_error_note(ira->codegen, msg, source_node,
8298 buf_sprintf("cast discards const qualifier"));
8299 return ira->codegen->invalid_inst_gen;
8300 }
8301 }
8302 }
8303
8304 // cast from undefined to anything
8305 if (actual_type->id == ZigTypeIdUndefined) {
8306 return ir_analyze_undefined_to_anything(ira, scope, source_node, value, wanted_type);
8307 }
8308
8309 // T to ?U, where T implicitly casts to U
8310 if (wanted_type->id == ZigTypeIdOptional && actual_type->id != ZigTypeIdOptional) {
8311 Stage1AirInst *cast1 = ir_implicit_cast2(ira, scope, source_node, value, wanted_type->data.maybe.child_type);
8312 if (type_is_invalid(cast1->value->type))
8313 return ira->codegen->invalid_inst_gen;
8314 return ir_implicit_cast2(ira, scope, source_node, cast1, wanted_type);
8315 }
8316
8317 // T to E!U, where T implicitly casts to U
8318 if (wanted_type->id == ZigTypeIdErrorUnion && actual_type->id != ZigTypeIdErrorUnion &&
8319 actual_type->id != ZigTypeIdErrorSet)
8320 {
8321 Stage1AirInst *cast1 = ir_implicit_cast2(ira, scope, source_node, value, wanted_type->data.error_union.payload_type);
8322 if (type_is_invalid(cast1->value->type))
8323 return ira->codegen->invalid_inst_gen;
8324 return ir_implicit_cast2(ira, scope, source_node, cast1, wanted_type);
8325 }
8326
8327 // E!T to T
8328 if (actual_type->id == ZigTypeIdErrorUnion) {
8329 if (types_match_const_cast_only(ira, actual_type->data.error_union.payload_type, wanted_type,
8330 source_node, false).id == ConstCastResultIdOk)
8331 {
8332 ErrorMsg *parent_msg = ir_add_error_node(ira, source_node,
8333 buf_sprintf("cannot convert error union to payload type. consider using `try`, `catch`, or `if`. expected type '%s', found '%s'",
8334 buf_ptr(&wanted_type->name),
8335 buf_ptr(&actual_type->name)));
8336 report_recursive_error(ira, source_node, &const_cast_result, parent_msg);
8337 return ira->codegen->invalid_inst_gen;
8338 }
8339 }
8340
8341 //?T to T
8342 if (actual_type->id == ZigTypeIdOptional) {
8343 if (types_match_const_cast_only(ira, actual_type->data.maybe.child_type, wanted_type,
8344 source_node, false).id == ConstCastResultIdOk)
8345 {
8346 ErrorMsg *parent_msg = ir_add_error_node(ira, source_node,
8347 buf_sprintf("cannot convert optional to payload type. consider using `.?`, `orelse`, or `if`. expected type '%s', found '%s'",
8348 buf_ptr(&wanted_type->name),
8349 buf_ptr(&actual_type->name)));
8350 report_recursive_error(ira, source_node, &const_cast_result, parent_msg);
8351 return ira->codegen->invalid_inst_gen;
8352 }
8353 }
8354
8355 ErrorMsg *parent_msg = ir_add_error_node(ira, source_node,
8356 buf_sprintf("expected type '%s', found '%s'",
8357 buf_ptr(&wanted_type->name),
8358 buf_ptr(&actual_type->name)));
8359 report_recursive_error(ira, source_node, &const_cast_result, parent_msg);
8360 return ira->codegen->invalid_inst_gen;
8361}
8362
8363static Stage1AirInst *ir_implicit_cast2(IrAnalyze *ira, Scope *scope, AstNode *source_node,
8364 Stage1AirInst *value, ZigType *expected_type)
8365{
8366 assert(value);
8367 assert(!expected_type || !type_is_invalid(expected_type));
8368 assert(value->value->type);
8369 assert(!type_is_invalid(value->value->type));
8370 if (expected_type == nullptr)
8371 return value; // anything will do
8372 if (expected_type == value->value->type)
8373 return value; // match
8374 if (value->value->type->id == ZigTypeIdUnreachable)
8375 return value;
8376
8377 return ir_analyze_cast(ira, scope, source_node, expected_type, value);
8378}
8379
8380static Stage1AirInst *ir_implicit_cast(IrAnalyze *ira, Stage1AirInst *value, ZigType *expected_type) {
8381 return ir_implicit_cast2(ira, value->scope, value->source_node, value, expected_type);
8382}
8383
8384static ZigType *get_ptr_elem_type(CodeGen *g, Stage1AirInst *ptr) {
8385 ir_assert(ptr->value->type->id == ZigTypeIdPointer, ptr);
8386 ZigType *elem_type = ptr->value->type->data.pointer.child_type;
8387 if (elem_type != g->builtin_types.entry_anytype)
8388 return elem_type;
8389
8390 if (ir_resolve_lazy(g, ptr->source_node, ptr->value))
8391 return g->builtin_types.entry_invalid;
8392
8393 assert(value_is_comptime(ptr->value));
8394 ZigValue *pointee = const_ptr_pointee_unchecked(g, ptr->value);
8395 return pointee->type;
8396}
8397
8398static Stage1AirInst *ir_get_deref(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *ptr,
8399 ResultLoc *result_loc)
8400{
8401 Error err;
8402 ZigType *ptr_type = ptr->value->type;
8403 if (type_is_invalid(ptr_type))
8404 return ira->codegen->invalid_inst_gen;
8405
8406 if (ptr_type->id != ZigTypeIdPointer) {
8407 ir_add_error_node(ira, source_node,
8408 buf_sprintf("attempt to dereference non-pointer type '%s'",
8409 buf_ptr(&ptr_type->name)));
8410 return ira->codegen->invalid_inst_gen;
8411 }
8412
8413 ZigType *child_type = ptr_type->data.pointer.child_type;
8414 if (type_is_invalid(child_type))
8415 return ira->codegen->invalid_inst_gen;
8416 // if the child type has one possible value, the deref is comptime
8417 switch (type_has_one_possible_value(ira->codegen, child_type)) {
8418 case OnePossibleValueInvalid:
8419 return ira->codegen->invalid_inst_gen;
8420 case OnePossibleValueYes:
8421 return ir_const_move(ira, scope, source_node,
8422 get_the_one_possible_value(ira->codegen, child_type));
8423 case OnePossibleValueNo:
8424 break;
8425 }
8426 if (instr_is_comptime(ptr)) {
8427 if (ptr->value->special == ConstValSpecialUndef) {
8428 // If we are in a TypeOf call, we return an undefined value instead of erroring
8429 // since we know the type.
8430 if (get_scope_typeof(scope)) {
8431 return ir_const_undef(ira, scope, source_node, child_type);
8432 }
8433
8434 ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value"));
8435 return ira->codegen->invalid_inst_gen;
8436 }
8437 if (ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
8438 ZigValue *pointee = const_ptr_pointee_unchecked(ira->codegen, ptr->value);
8439 if (child_type == ira->codegen->builtin_types.entry_anytype) {
8440 child_type = pointee->type;
8441 }
8442 if (pointee->special != ConstValSpecialRuntime) {
8443 Stage1AirInst *result = ir_const(ira, scope, source_node, child_type);
8444
8445 if ((err = ir_read_const_ptr(ira, ira->codegen, source_node, result->value,
8446 ptr->value)))
8447 {
8448 return ira->codegen->invalid_inst_gen;
8449 }
8450 result->value->type = child_type;
8451 return result;
8452 }
8453 }
8454 }
8455
8456 // if the instruction is a const ref instruction we can skip it
8457 if (ptr->id == Stage1AirInstIdRef) {
8458 Stage1AirInstRef *ref_inst = reinterpret_cast<Stage1AirInstRef *>(ptr);
8459 return ref_inst->operand;
8460 }
8461
8462 // If the instruction is a element pointer instruction to a vector, we emit
8463 // vector element extract instruction rather than load pointer. If the
8464 // pointer type has non-VECTOR_INDEX_RUNTIME value, it would have been
8465 // possible to implement this in the codegen for Stage1AirInstLoadPtr.
8466 // However if it has VECTOR_INDEX_RUNTIME then we must emit a compile error
8467 // if the vector index cannot be determined right here, right now, because
8468 // the type information does not contain enough information to actually
8469 // perform a dereference.
8470 if (ptr_type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) {
8471 if (ptr->id == Stage1AirInstIdElemPtr) {
8472 Stage1AirInstElemPtr *elem_ptr = (Stage1AirInstElemPtr *)ptr;
8473 Stage1AirInst *vector_loaded = ir_get_deref(ira, elem_ptr->array_ptr->scope,
8474 elem_ptr->array_ptr->source_node, elem_ptr->array_ptr, nullptr);
8475 Stage1AirInst *elem_index = elem_ptr->elem_index;
8476 return ir_build_vector_extract_elem(ira, scope, source_node, vector_loaded, elem_index);
8477 }
8478 ir_add_error(ira, ptr,
8479 buf_sprintf("unable to determine vector element index of type '%s'", buf_ptr(&ptr_type->name)));
8480 return ira->codegen->invalid_inst_gen;
8481 }
8482
8483 Stage1AirInst *result_loc_inst;
8484 if (ptr_type->data.pointer.host_int_bytes != 0 && handle_is_ptr(ira->codegen, child_type)) {
8485 if (result_loc == nullptr) result_loc = no_result_loc();
8486 result_loc_inst = ir_resolve_result(ira, ira->suspend_source_instr, result_loc, child_type, nullptr, true, true);
8487 if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
8488 return result_loc_inst;
8489 }
8490 } else {
8491 result_loc_inst = nullptr;
8492 }
8493
8494 return ir_build_load_ptr_gen(ira, scope, source_node, ptr, child_type, result_loc_inst);
8495}
8496
8497static bool ir_resolve_const_align(CodeGen *codegen, Stage1Air *exec, AstNode *source_node,
8498 ZigValue *const_val, uint32_t *out)
8499{
8500 Error err;
8501 if ((err = ir_resolve_const_val(codegen, exec, source_node, const_val, UndefBad)))
8502 return false;
8503
8504 uint32_t align_bytes = bigint_as_u32(&const_val->data.x_bigint);
8505 if (align_bytes == 0) {
8506 exec_add_error_node_gen(codegen, exec, source_node, buf_sprintf("alignment must be >= 1"));
8507 return false;
8508 }
8509
8510 if (!is_power_of_2(align_bytes)) {
8511 exec_add_error_node_gen(codegen, exec, source_node,
8512 buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes));
8513 return false;
8514 }
8515
8516 *out = align_bytes;
8517 return true;
8518}
8519
8520static bool ir_resolve_align(IrAnalyze *ira, Stage1AirInst *value, ZigType *elem_type, uint32_t *out) {
8521 if (type_is_invalid(value->value->type))
8522 return false;
8523
8524 // Look for this pattern: `*align(@alignOf(T)) T`.
8525 // This can be resolved to be `*out = 0` without resolving any alignment.
8526 if (elem_type != nullptr && value->value->special == ConstValSpecialLazy &&
8527 value->value->data.x_lazy->id == LazyValueIdAlignOf)
8528 {
8529 LazyValueAlignOf *lazy_align_of = reinterpret_cast<LazyValueAlignOf *>(value->value->data.x_lazy);
8530
8531 ZigType *lazy_elem_type = ir_resolve_type(lazy_align_of->ira, lazy_align_of->target_type);
8532 if (type_is_invalid(lazy_elem_type))
8533 return false;
8534
8535 if (elem_type == lazy_elem_type) {
8536 *out = 0;
8537 return true;
8538 }
8539 }
8540
8541 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen));
8542 if (type_is_invalid(casted_value->value->type))
8543 return false;
8544
8545 return ir_resolve_const_align(ira->codegen, ira->new_irb.exec, value->source_node,
8546 casted_value->value, out);
8547}
8548
8549static bool ir_resolve_unsigned(IrAnalyze *ira, Stage1AirInst *value, ZigType *int_type, uint64_t *out) {
8550 if (type_is_invalid(value->value->type))
8551 return false;
8552
8553 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, int_type);
8554 if (type_is_invalid(casted_value->value->type))
8555 return false;
8556
8557 ZigValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
8558 if (!const_val)
8559 return false;
8560
8561 *out = bigint_as_u64(&const_val->data.x_bigint);
8562 return true;
8563}
8564
8565static bool ir_resolve_usize(IrAnalyze *ira, Stage1AirInst *value, uint64_t *out) {
8566 return ir_resolve_unsigned(ira, value, ira->codegen->builtin_types.entry_usize, out);
8567}
8568
8569static bool ir_resolve_bool(IrAnalyze *ira, Stage1AirInst *value, bool *out) {
8570 if (type_is_invalid(value->value->type))
8571 return false;
8572
8573 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_bool);
8574 if (type_is_invalid(casted_value->value->type))
8575 return false;
8576
8577 ZigValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
8578 if (!const_val)
8579 return false;
8580
8581 *out = const_val->data.x_bool;
8582 return true;
8583}
8584
8585static bool ir_resolve_comptime(IrAnalyze *ira, Stage1AirInst *value, bool *out) {
8586 if (!value) {
8587 *out = false;
8588 return true;
8589 }
8590 return ir_resolve_bool(ira, value, out);
8591}
8592
8593static bool ir_resolve_reduce_op(IrAnalyze *ira, Stage1AirInst *value, ReduceOp *out) {
8594 if (type_is_invalid(value->value->type))
8595 return false;
8596
8597 ZigType *reduce_op_type = get_builtin_type(ira->codegen, "ReduceOp");
8598
8599 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, reduce_op_type);
8600 if (type_is_invalid(casted_value->value->type))
8601 return false;
8602
8603 ZigValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
8604 if (!const_val)
8605 return false;
8606
8607 *out = (ReduceOp)bigint_as_u32(&const_val->data.x_enum_tag);
8608 return true;
8609}
8610
8611static bool ir_resolve_atomic_order(IrAnalyze *ira, Stage1AirInst *value, AtomicOrder *out) {
8612 if (type_is_invalid(value->value->type))
8613 return false;
8614
8615 ZigType *atomic_order_type = get_builtin_type(ira->codegen, "AtomicOrder");
8616
8617 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, atomic_order_type);
8618 if (type_is_invalid(casted_value->value->type))
8619 return false;
8620
8621 ZigValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
8622 if (!const_val)
8623 return false;
8624
8625 *out = (AtomicOrder)bigint_as_u32(&const_val->data.x_enum_tag);
8626 return true;
8627}
8628
8629static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, Stage1AirInst *value, AtomicRmwOp *out) {
8630 if (type_is_invalid(value->value->type))
8631 return false;
8632
8633 ZigType *atomic_rmw_op_type = get_builtin_type(ira->codegen, "AtomicRmwOp");
8634
8635 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, atomic_rmw_op_type);
8636 if (type_is_invalid(casted_value->value->type))
8637 return false;
8638
8639 ZigValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
8640 if (!const_val)
8641 return false;
8642
8643 *out = (AtomicRmwOp)bigint_as_u32(&const_val->data.x_enum_tag);
8644 return true;
8645}
8646
8647static bool ir_resolve_global_linkage(IrAnalyze *ira, Stage1AirInst *value, GlobalLinkageId *out) {
8648 if (type_is_invalid(value->value->type))
8649 return false;
8650
8651 ZigType *global_linkage_type = get_builtin_type(ira->codegen, "GlobalLinkage");
8652
8653 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, global_linkage_type);
8654 if (type_is_invalid(casted_value->value->type))
8655 return false;
8656
8657 ZigValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
8658 if (!const_val)
8659 return false;
8660
8661 *out = (GlobalLinkageId)bigint_as_u32(&const_val->data.x_enum_tag);
8662 return true;
8663}
8664
8665static bool ir_resolve_float_mode(IrAnalyze *ira, Stage1AirInst *value, FloatMode *out) {
8666 if (type_is_invalid(value->value->type))
8667 return false;
8668
8669 ZigType *float_mode_type = get_builtin_type(ira->codegen, "FloatMode");
8670
8671 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, float_mode_type);
8672 if (type_is_invalid(casted_value->value->type))
8673 return false;
8674
8675 ZigValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
8676 if (!const_val)
8677 return false;
8678
8679 *out = (FloatMode)bigint_as_u32(&const_val->data.x_enum_tag);
8680 return true;
8681}
8682
8683static Buf *ir_resolve_str(IrAnalyze *ira, Stage1AirInst *value) {
8684 if (type_is_invalid(value->value->type))
8685 return nullptr;
8686
8687 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
8688 true, false, PtrLenUnknown, 0, 0, 0, false);
8689 ZigType *str_type = get_slice_type(ira->codegen, ptr_type);
8690 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, str_type);
8691 if (type_is_invalid(casted_value->value->type))
8692 return nullptr;
8693
8694 ZigValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
8695 if (!const_val)
8696 return nullptr;
8697
8698 ZigValue *ptr_field = const_val->data.x_struct.fields[slice_ptr_index];
8699 ZigValue *len_field = const_val->data.x_struct.fields[slice_len_index];
8700
8701 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
8702 ZigValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;
8703 expand_undef_array(ira->codegen, array_val);
8704 size_t len = bigint_as_usize(&len_field->data.x_bigint);
8705 if (array_val->data.x_array.special == ConstArraySpecialBuf && len == buf_len(array_val->data.x_array.data.s_buf)) {
8706 return array_val->data.x_array.data.s_buf;
8707 }
8708 Buf *result = buf_alloc();
8709 buf_resize(result, len);
8710 for (size_t i = 0; i < len; i += 1) {
8711 size_t new_index = ptr_field->data.x_ptr.data.base_array.elem_index + i;
8712 ZigValue *char_val = &array_val->data.x_array.data.s_none.elements[new_index];
8713 if (char_val->special == ConstValSpecialUndef) {
8714 ir_add_error(ira, casted_value, buf_sprintf("use of undefined value"));
8715 return nullptr;
8716 }
8717 uint64_t big_c = bigint_as_u64(&char_val->data.x_bigint);
8718 assert(big_c <= UINT8_MAX);
8719 uint8_t c = (uint8_t)big_c;
8720 buf_ptr(result)[i] = c;
8721 }
8722 return result;
8723}
8724
8725static Stage1AirInst *ir_analyze_instruction_add_implicit_return_type(IrAnalyze *ira,
8726 Stage1ZirInstAddImplicitReturnType *instruction)
8727{
8728 Stage1AirInst *value = instruction->value->child;
8729 if (type_is_invalid(value->value->type))
8730 return ir_unreach_error(ira);
8731
8732 if (instruction->result_loc_ret == nullptr || !instruction->result_loc_ret->implicit_return_type_done) {
8733 ira->src_implicit_return_type_list.append(value);
8734 }
8735
8736 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
8737}
8738
8739static Stage1AirInst *ir_analyze_instruction_return(IrAnalyze *ira, Stage1ZirInstReturn *instruction) {
8740 if (instruction->operand == nullptr) {
8741 // result location mechanism took care of it.
8742 Stage1AirInst *result = ir_build_return_gen(ira, instruction->base.scope, instruction->base.source_node, nullptr);
8743 return ir_finish_anal(ira, result);
8744 }
8745
8746 Stage1AirInst *operand = instruction->operand->child;
8747 if (type_is_invalid(operand->value->type))
8748 return ir_unreach_error(ira);
8749
8750 Stage1AirInst *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type);
8751 if (type_is_invalid(casted_operand->value->type)) {
8752 AstNode *source_node = ira->explicit_return_type_source_node;
8753 if (source_node != nullptr) {
8754 ErrorMsg *msg = ira->codegen->errors.last();
8755 add_error_note(ira->codegen, msg, source_node,
8756 buf_sprintf("return type declared here"));
8757 }
8758 return ir_unreach_error(ira);
8759 }
8760
8761 if (!instr_is_comptime(operand) && ira->explicit_return_type != nullptr &&
8762 handle_is_ptr(ira->codegen, ira->explicit_return_type))
8763 {
8764 // result location mechanism took care of it.
8765 Stage1AirInst *result = ir_build_return_gen(ira, instruction->base.scope, instruction->base.source_node, nullptr);
8766 return ir_finish_anal(ira, result);
8767 }
8768
8769 if (casted_operand->value->special == ConstValSpecialRuntime &&
8770 casted_operand->value->type->id == ZigTypeIdPointer &&
8771 casted_operand->value->data.rh_ptr == RuntimeHintPtrStack)
8772 {
8773 ir_add_error_node(ira, instruction->operand->source_node,
8774 buf_sprintf("function returns address of local variable"));
8775 return ir_unreach_error(ira);
8776 }
8777
8778 Stage1AirInst *result = ir_build_return_gen(ira, instruction->base.scope, instruction->base.source_node, casted_operand);
8779 return ir_finish_anal(ira, result);
8780}
8781
8782static Stage1AirInst *ir_analyze_instruction_const(IrAnalyze *ira, Stage1ZirInstConst *instruction) {
8783 return ir_const_move(ira, instruction->base.scope, instruction->base.source_node, instruction->value);
8784}
8785
8786static Stage1AirInst *ir_analyze_bin_op_bool(IrAnalyze *ira, Stage1ZirInstBinOp *bin_op_instruction) {
8787 Stage1AirInst *op1 = bin_op_instruction->op1->child;
8788 if (type_is_invalid(op1->value->type))
8789 return ira->codegen->invalid_inst_gen;
8790
8791 Stage1AirInst *op2 = bin_op_instruction->op2->child;
8792 if (type_is_invalid(op2->value->type))
8793 return ira->codegen->invalid_inst_gen;
8794
8795 ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
8796
8797 Stage1AirInst *casted_op1 = ir_implicit_cast(ira, op1, bool_type);
8798 if (type_is_invalid(casted_op1->value->type))
8799 return ira->codegen->invalid_inst_gen;
8800
8801 Stage1AirInst *casted_op2 = ir_implicit_cast(ira, op2, bool_type);
8802 if (type_is_invalid(casted_op2->value->type))
8803 return ira->codegen->invalid_inst_gen;
8804
8805 if (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2)) {
8806 ZigValue *op1_val = ir_resolve_const(ira, casted_op1, UndefBad);
8807 if (op1_val == nullptr)
8808 return ira->codegen->invalid_inst_gen;
8809
8810 ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
8811 if (op2_val == nullptr)
8812 return ira->codegen->invalid_inst_gen;
8813
8814 assert(casted_op1->value->type->id == ZigTypeIdBool);
8815 assert(casted_op2->value->type->id == ZigTypeIdBool);
8816 bool result_bool;
8817 if (bin_op_instruction->op_id == IrBinOpBoolOr) {
8818 result_bool = op1_val->data.x_bool || op2_val->data.x_bool;
8819 } else if (bin_op_instruction->op_id == IrBinOpBoolAnd) {
8820 result_bool = op1_val->data.x_bool && op2_val->data.x_bool;
8821 } else {
8822 zig_unreachable();
8823 }
8824 return ir_const_bool(ira, bin_op_instruction->base.scope,
8825 bin_op_instruction->base.source_node, result_bool);
8826 }
8827
8828 return ir_build_bin_op_gen(ira, bin_op_instruction->base.scope,
8829 bin_op_instruction->base.source_node, bool_type, bin_op_instruction->op_id,
8830 casted_op1, casted_op2, bin_op_instruction->safety_check_on);
8831}
8832
8833static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
8834 switch (op_id) {
8835 case IrBinOpCmpEq:
8836 return cmp == CmpEQ;
8837 case IrBinOpCmpNotEq:
8838 return cmp != CmpEQ;
8839 case IrBinOpCmpLessThan:
8840 return cmp == CmpLT;
8841 case IrBinOpCmpGreaterThan:
8842 return cmp == CmpGT;
8843 case IrBinOpCmpLessOrEq:
8844 return cmp != CmpGT;
8845 case IrBinOpCmpGreaterOrEq:
8846 return cmp != CmpLT;
8847 default:
8848 zig_unreachable();
8849 }
8850}
8851
8852static void set_optional_value_to_null(ZigValue *val) {
8853 assert(val->special == ConstValSpecialStatic);
8854 if (val->type->id == ZigTypeIdNull) return; // nothing to do
8855 assert(val->type->id == ZigTypeIdOptional);
8856 if (get_src_ptr_type(val->type) != nullptr) {
8857 val->data.x_ptr.special = ConstPtrSpecialNull;
8858 } else if (is_opt_err_set(val->type)) {
8859 val->data.x_err_set = nullptr;
8860 } else {
8861 val->data.x_optional = nullptr;
8862 }
8863}
8864
8865static void set_optional_payload(ZigValue *opt_val, ZigValue *payload) {
8866 assert(opt_val->special == ConstValSpecialStatic);
8867 assert(opt_val->type->id == ZigTypeIdOptional);
8868 if (payload == nullptr) {
8869 set_optional_value_to_null(opt_val);
8870 } else if (get_src_ptr_type(opt_val->type)) {
8871 assert(get_src_ptr_type(payload->type));
8872 opt_val->data.x_ptr = payload->data.x_ptr;
8873 } else if (is_opt_err_set(opt_val->type)) {
8874 assert(payload->type->id == ZigTypeIdErrorSet);
8875 opt_val->data.x_err_set = payload->data.x_err_set;
8876 } else {
8877 opt_val->data.x_optional = payload;
8878 }
8879}
8880
8881static Stage1AirInst *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_type,
8882 ZigValue *op1_val, ZigValue *op2_val, Scope *scope, AstNode *source_node, IrBinOp op_id,
8883 bool one_possible_value)
8884{
8885 if (op1_val->special == ConstValSpecialUndef ||
8886 op2_val->special == ConstValSpecialUndef)
8887 return ir_const_undef(ira, scope, source_node, resolved_type);
8888 if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) {
8889 if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
8890 op1_val->data.x_ptr.special == ConstPtrSpecialNull) &&
8891 (op2_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
8892 op2_val->data.x_ptr.special == ConstPtrSpecialNull))
8893 {
8894 uint64_t op1_addr = op1_val->data.x_ptr.special == ConstPtrSpecialNull ?
8895 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr;
8896 uint64_t op2_addr = op2_val->data.x_ptr.special == ConstPtrSpecialNull ?
8897 0 : op2_val->data.x_ptr.data.hard_coded_addr.addr;
8898 Cmp cmp_result;
8899 if (op1_addr > op2_addr) {
8900 cmp_result = CmpGT;
8901 } else if (op1_addr < op2_addr) {
8902 cmp_result = CmpLT;
8903 } else {
8904 cmp_result = CmpEQ;
8905 }
8906 bool answer = resolve_cmp_op_id(op_id, cmp_result);
8907 return ir_const_bool(ira, scope, source_node, answer);
8908 }
8909 } else {
8910 bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);
8911 bool answer;
8912 if (op_id == IrBinOpCmpEq) {
8913 answer = are_equal;
8914 } else if (op_id == IrBinOpCmpNotEq) {
8915 answer = !are_equal;
8916 } else {
8917 zig_unreachable();
8918 }
8919 return ir_const_bool(ira, scope, source_node, answer);
8920 }
8921 zig_unreachable();
8922}
8923
8924static Stage1AirInst *ir_try_evaluate_bin_op_cmp_const(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *op1, Stage1AirInst *op2,
8925 ZigType *resolved_type, IrBinOp op_id)
8926{
8927 assert(op1->value->type == resolved_type && op2->value->type == resolved_type);
8928 bool one_possible_value;
8929 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
8930 case OnePossibleValueInvalid:
8931 return ira->codegen->invalid_inst_gen;
8932 case OnePossibleValueYes:
8933 one_possible_value = true;
8934 break;
8935 case OnePossibleValueNo:
8936 one_possible_value = false;
8937 break;
8938 }
8939
8940 if (one_possible_value || (instr_is_comptime(op1) && instr_is_comptime(op2))) {
8941 ZigValue *op1_val = one_possible_value ? op1->value : ir_resolve_const(ira, op1, UndefBad);
8942 if (op1_val == nullptr)
8943 return ira->codegen->invalid_inst_gen;
8944 ZigValue *op2_val = one_possible_value ? op2->value : ir_resolve_const(ira, op2, UndefBad);
8945 if (op2_val == nullptr)
8946 return ira->codegen->invalid_inst_gen;
8947 if (resolved_type->id != ZigTypeIdVector)
8948 return ir_evaluate_bin_op_cmp(ira, resolved_type, op1_val, op2_val, scope, source_node, op_id, one_possible_value);
8949 Stage1AirInst *result = ir_const(ira, scope, source_node,
8950 get_vector_type(ira->codegen, resolved_type->data.vector.len, ira->codegen->builtin_types.entry_bool));
8951 result->value->data.x_array.data.s_none.elements =
8952 ira->codegen->pass1_arena->allocate<ZigValue>(resolved_type->data.vector.len);
8953
8954 expand_undef_array(ira->codegen, result->value);
8955 for (size_t i = 0;i < resolved_type->data.vector.len;i++) {
8956 Stage1AirInst *cur_res = ir_evaluate_bin_op_cmp(ira, resolved_type->data.vector.elem_type,
8957 &op1_val->data.x_array.data.s_none.elements[i],
8958 &op2_val->data.x_array.data.s_none.elements[i],
8959 scope, source_node, op_id, one_possible_value);
8960 copy_const_val(ira->codegen, &result->value->data.x_array.data.s_none.elements[i], cur_res->value);
8961 }
8962 return result;
8963 } else {
8964 return nullptr;
8965 }
8966}
8967
8968// Returns ErrorNotLazy when the value cannot be determined
8969static Error lazy_cmp_zero(CodeGen *codegen, AstNode *source_node, ZigValue *val, Cmp *result) {
8970 Error err;
8971
8972 switch (type_has_one_possible_value(codegen, val->type)) {
8973 case OnePossibleValueInvalid:
8974 return ErrorSemanticAnalyzeFail;
8975 case OnePossibleValueNo:
8976 break;
8977 case OnePossibleValueYes:
8978 switch (val->type->id) {
8979 case ZigTypeIdInt:
8980 src_assert(val->type->data.integral.bit_count == 0, source_node);
8981 *result = CmpEQ;
8982 return ErrorNone;
8983 case ZigTypeIdUndefined:
8984 return ErrorNotLazy;
8985 default:
8986 zig_unreachable();
8987 }
8988 }
8989
8990 switch (val->special) {
8991 case ConstValSpecialRuntime:
8992 case ConstValSpecialUndef:
8993 return ErrorNotLazy;
8994 case ConstValSpecialStatic:
8995 switch (val->type->id) {
8996 case ZigTypeIdComptimeInt:
8997 case ZigTypeIdInt:
8998 *result = bigint_cmp_zero(&val->data.x_bigint);
8999 return ErrorNone;
9000 case ZigTypeIdComptimeFloat:
9001 case ZigTypeIdFloat:
9002 if (float_is_nan(val))
9003 return ErrorNotLazy;
9004 *result = float_cmp_zero(val);
9005 return ErrorNone;
9006 default:
9007 return ErrorNotLazy;
9008 }
9009 case ConstValSpecialLazy:
9010 switch (val->data.x_lazy->id) {
9011 case LazyValueIdInvalid:
9012 zig_unreachable();
9013 case LazyValueIdAlignOf: {
9014 LazyValueAlignOf *lazy_align_of = reinterpret_cast<LazyValueAlignOf *>(val->data.x_lazy);
9015 IrAnalyze *ira = lazy_align_of->ira;
9016
9017 bool is_zero_bits;
9018 if ((err = type_val_resolve_zero_bits(ira->codegen, lazy_align_of->target_type->value,
9019 nullptr, nullptr, &is_zero_bits)))
9020 {
9021 return err;
9022 }
9023
9024 *result = is_zero_bits ? CmpEQ : CmpGT;
9025 return ErrorNone;
9026 }
9027 case LazyValueIdSizeOf: {
9028 LazyValueSizeOf *lazy_size_of = reinterpret_cast<LazyValueSizeOf *>(val->data.x_lazy);
9029 IrAnalyze *ira = lazy_size_of->ira;
9030 bool is_zero_bits;
9031 if ((err = type_val_resolve_zero_bits(ira->codegen, lazy_size_of->target_type->value,
9032 nullptr, nullptr, &is_zero_bits)))
9033 {
9034 return err;
9035 }
9036 *result = is_zero_bits ? CmpEQ : CmpGT;
9037 return ErrorNone;
9038 }
9039 default:
9040 return ErrorNotLazy;
9041 }
9042 }
9043 zig_unreachable();
9044}
9045
9046static ErrorMsg *ir_eval_bin_op_cmp_scalar(IrAnalyze *ira, Scope *scope, AstNode *source_node,
9047 ZigValue *op1_val, IrBinOp op_id, ZigValue *op2_val, ZigValue *out_val)
9048{
9049 Error err;
9050 {
9051 // Before resolving the values, we special case comparisons against zero. These can often
9052 // be done without resolving lazy values, preventing potential dependency loops.
9053 Cmp op1_cmp_zero;
9054 if ((err = lazy_cmp_zero(ira->codegen, source_node, op1_val, &op1_cmp_zero))) {
9055 if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally;
9056 return ira->codegen->trace_err;
9057 }
9058 Cmp op2_cmp_zero;
9059 if ((err = lazy_cmp_zero(ira->codegen, source_node, op2_val, &op2_cmp_zero))) {
9060 if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally;
9061 return ira->codegen->trace_err;
9062 }
9063 bool can_cmp_zero = false;
9064 Cmp cmp_result;
9065 if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpEQ) {
9066 can_cmp_zero = true;
9067 cmp_result = CmpEQ;
9068 } else if (op1_cmp_zero == CmpGT && op2_cmp_zero == CmpEQ) {
9069 can_cmp_zero = true;
9070 cmp_result = CmpGT;
9071 } else if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpGT) {
9072 can_cmp_zero = true;
9073 cmp_result = CmpLT;
9074 } else if (op1_cmp_zero == CmpLT && op2_cmp_zero == CmpEQ) {
9075 can_cmp_zero = true;
9076 cmp_result = CmpLT;
9077 } else if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpLT) {
9078 can_cmp_zero = true;
9079 cmp_result = CmpGT;
9080 } else if (op1_cmp_zero == CmpLT && op2_cmp_zero == CmpGT) {
9081 can_cmp_zero = true;
9082 cmp_result = CmpLT;
9083 } else if (op1_cmp_zero == CmpGT && op2_cmp_zero == CmpLT) {
9084 can_cmp_zero = true;
9085 cmp_result = CmpGT;
9086 }
9087 if (can_cmp_zero) {
9088 bool answer = resolve_cmp_op_id(op_id, cmp_result);
9089 out_val->special = ConstValSpecialStatic;
9090 out_val->data.x_bool = answer;
9091 return nullptr;
9092 }
9093 }
9094never_mind_just_calculate_it_normally:
9095
9096 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, source_node,
9097 op1_val, UndefOk)))
9098 {
9099 return ira->codegen->trace_err;
9100 }
9101 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, source_node,
9102 op2_val, UndefOk)))
9103 {
9104 return ira->codegen->trace_err;
9105 }
9106
9107
9108 if (op1_val->special == ConstValSpecialUndef || op2_val->special == ConstValSpecialUndef ||
9109 op1_val->type->id == ZigTypeIdUndefined || op2_val->type->id == ZigTypeIdUndefined)
9110 {
9111 out_val->special = ConstValSpecialUndef;
9112 return nullptr;
9113 }
9114
9115 bool op1_is_float = op1_val->type->id == ZigTypeIdFloat || op1_val->type->id == ZigTypeIdComptimeFloat;
9116 bool op2_is_float = op2_val->type->id == ZigTypeIdFloat || op2_val->type->id == ZigTypeIdComptimeFloat;
9117 if (op1_is_float && op2_is_float) {
9118 if (float_is_nan(op1_val) || float_is_nan(op2_val)) {
9119 out_val->special = ConstValSpecialStatic;
9120 out_val->data.x_bool = op_id == IrBinOpCmpNotEq;
9121 return nullptr;
9122 }
9123 if (op1_val->type->id == ZigTypeIdComptimeFloat) {
9124 Stage1AirInst *tmp = ir_const_noval(ira, scope, source_node);
9125 tmp->value = op1_val;
9126 Stage1AirInst *casted = ir_implicit_cast(ira, tmp, op2_val->type);
9127 op1_val = casted->value;
9128 } else if (op2_val->type->id == ZigTypeIdComptimeFloat) {
9129 Stage1AirInst *tmp = ir_const_noval(ira, scope, source_node);
9130 tmp->value = op2_val;
9131 Stage1AirInst *casted = ir_implicit_cast(ira, tmp, op1_val->type);
9132 op2_val = casted->value;
9133 }
9134 Cmp cmp_result = float_cmp(op1_val, op2_val);
9135 out_val->special = ConstValSpecialStatic;
9136 out_val->data.x_bool = resolve_cmp_op_id(op_id, cmp_result);
9137 return nullptr;
9138 }
9139
9140 bool op1_is_int = op1_val->type->id == ZigTypeIdInt || op1_val->type->id == ZigTypeIdComptimeInt;
9141 bool op2_is_int = op2_val->type->id == ZigTypeIdInt || op2_val->type->id == ZigTypeIdComptimeInt;
9142
9143 if (op1_is_int && op2_is_int) {
9144 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
9145 out_val->special = ConstValSpecialStatic;
9146 out_val->data.x_bool = resolve_cmp_op_id(op_id, cmp_result);
9147
9148 return nullptr;
9149 }
9150
9151 // Handle the case where one of the two operands is a fp value and the other
9152 // is an integer value
9153 ZigValue *float_val;
9154 if (op1_is_int && op2_is_float) {
9155 float_val = op2_val;
9156 } else if (op1_is_float && op2_is_int) {
9157 float_val = op1_val;
9158 } else {
9159 zig_unreachable();
9160 }
9161
9162 // They can never be equal if the fp value has a non-zero decimal part
9163 if (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq) {
9164 if (float_has_fraction(float_val)) {
9165 out_val->special = ConstValSpecialStatic;
9166 out_val->data.x_bool = op_id == IrBinOpCmpNotEq;
9167 return nullptr;
9168 }
9169 }
9170
9171 // Cast the integer operand into a fp value to perform the comparison
9172 BigFloat op1_bigfloat;
9173 BigFloat op2_bigfloat;
9174 value_to_bigfloat(&op1_bigfloat, op1_val);
9175 value_to_bigfloat(&op2_bigfloat, op2_val);
9176
9177 Cmp cmp_result = bigfloat_cmp(&op1_bigfloat, &op2_bigfloat);
9178 out_val->special = ConstValSpecialStatic;
9179 out_val->data.x_bool = resolve_cmp_op_id(op_id, cmp_result);
9180
9181 return nullptr;
9182}
9183
9184static Stage1AirInst *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, Scope *scope, AstNode *source_node,
9185 Stage1AirInst *op1, Stage1AirInst *op2, IrBinOp op_id)
9186{
9187 Error err;
9188
9189 ZigType *scalar_result_type = ira->codegen->builtin_types.entry_bool;
9190 ZigType *result_type = scalar_result_type;
9191 ZigType *op1_scalar_type = op1->value->type;
9192 ZigType *op2_scalar_type = op2->value->type;
9193 if (op1->value->type->id == ZigTypeIdVector && op2->value->type->id == ZigTypeIdVector) {
9194 if (op1->value->type->data.vector.len != op2->value->type->data.vector.len) {
9195 ir_add_error_node(ira, source_node,
9196 buf_sprintf("vector length mismatch: %" PRIu64 " and %" PRIu64,
9197 op1->value->type->data.vector.len, op2->value->type->data.vector.len));
9198 return ira->codegen->invalid_inst_gen;
9199 }
9200 result_type = get_vector_type(ira->codegen, op1->value->type->data.vector.len, scalar_result_type);
9201 op1_scalar_type = op1->value->type->data.vector.elem_type;
9202 op2_scalar_type = op2->value->type->data.vector.elem_type;
9203 } else if (op1->value->type->id == ZigTypeIdVector || op2->value->type->id == ZigTypeIdVector) {
9204 ir_add_error_node(ira, source_node,
9205 buf_sprintf("mixed scalar and vector operands to comparison operator: '%s' and '%s'",
9206 buf_ptr(&op1->value->type->name), buf_ptr(&op2->value->type->name)));
9207 return ira->codegen->invalid_inst_gen;
9208 }
9209
9210 bool opv_op1;
9211 switch (type_has_one_possible_value(ira->codegen, op1->value->type)) {
9212 case OnePossibleValueInvalid:
9213 return ira->codegen->invalid_inst_gen;
9214 case OnePossibleValueYes:
9215 opv_op1 = true;
9216 break;
9217 case OnePossibleValueNo:
9218 opv_op1 = false;
9219 break;
9220 }
9221 bool opv_op2;
9222 switch (type_has_one_possible_value(ira->codegen, op2->value->type)) {
9223 case OnePossibleValueInvalid:
9224 return ira->codegen->invalid_inst_gen;
9225 case OnePossibleValueYes:
9226 opv_op2 = true;
9227 break;
9228 case OnePossibleValueNo:
9229 opv_op2 = false;
9230 break;
9231 }
9232 Cmp op1_cmp_zero;
9233 bool have_op1_cmp_zero = false;
9234 if ((err = lazy_cmp_zero(ira->codegen, source_node, op1->value, &op1_cmp_zero))) {
9235 if (err != ErrorNotLazy) return ira->codegen->invalid_inst_gen;
9236 } else {
9237 have_op1_cmp_zero = true;
9238 }
9239 Cmp op2_cmp_zero;
9240 bool have_op2_cmp_zero = false;
9241 if ((err = lazy_cmp_zero(ira->codegen, source_node, op2->value, &op2_cmp_zero))) {
9242 if (err != ErrorNotLazy) return ira->codegen->invalid_inst_gen;
9243 } else {
9244 have_op2_cmp_zero = true;
9245 }
9246 if (((opv_op1 || instr_is_comptime(op1)) && (opv_op2 || instr_is_comptime(op2))) ||
9247 (have_op1_cmp_zero && have_op2_cmp_zero))
9248 {
9249 Stage1AirInst *result_instruction = ir_const(ira, scope, source_node, result_type);
9250 ZigValue *out_val = result_instruction->value;
9251 if (result_type->id == ZigTypeIdVector) {
9252 size_t len = result_type->data.vector.len;
9253 expand_undef_array(ira->codegen, op1->value);
9254 expand_undef_array(ira->codegen, op2->value);
9255 out_val->special = ConstValSpecialUndef;
9256 expand_undef_array(ira->codegen, out_val);
9257 for (size_t i = 0; i < len; i += 1) {
9258 ZigValue *scalar_op1_val = &op1->value->data.x_array.data.s_none.elements[i];
9259 ZigValue *scalar_op2_val = &op2->value->data.x_array.data.s_none.elements[i];
9260 ZigValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i];
9261 assert(scalar_out_val->type == scalar_result_type);
9262 ErrorMsg *msg = ir_eval_bin_op_cmp_scalar(ira, scope, source_node,
9263 scalar_op1_val, op_id, scalar_op2_val, scalar_out_val);
9264 if (msg != nullptr) {
9265 add_error_note(ira->codegen, msg, source_node,
9266 buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i));
9267 return ira->codegen->invalid_inst_gen;
9268 }
9269 }
9270 out_val->type = result_type;
9271 out_val->special = ConstValSpecialStatic;
9272 } else {
9273 if (ir_eval_bin_op_cmp_scalar(ira, scope, source_node, op1->value, op_id,
9274 op2->value, out_val) != nullptr)
9275 {
9276 return ira->codegen->invalid_inst_gen;
9277 }
9278 }
9279 return result_instruction;
9280 }
9281
9282 // If one operand has a comptime-known comparison with 0, and the other operand is unsigned, we might
9283 // know the answer, depending on the operator.
9284 // TODO make this work with vectors
9285 if (have_op1_cmp_zero && op2_scalar_type->id == ZigTypeIdInt && !op2_scalar_type->data.integral.is_signed) {
9286 if (op1_cmp_zero == CmpEQ) {
9287 // 0 <= unsigned_x // true
9288 // 0 > unsigned_x // false
9289 switch (op_id) {
9290 case IrBinOpCmpLessOrEq:
9291 return ir_const_bool(ira, scope, source_node, true);
9292 case IrBinOpCmpGreaterThan:
9293 return ir_const_bool(ira, scope, source_node, false);
9294 default:
9295 break;
9296 }
9297 } else if (op1_cmp_zero == CmpLT) {
9298 // -1 != unsigned_x // true
9299 // -1 <= unsigned_x // true
9300 // -1 < unsigned_x // true
9301 // -1 == unsigned_x // false
9302 // -1 >= unsigned_x // false
9303 // -1 > unsigned_x // false
9304 switch (op_id) {
9305 case IrBinOpCmpNotEq:
9306 case IrBinOpCmpLessOrEq:
9307 case IrBinOpCmpLessThan:
9308 return ir_const_bool(ira, scope, source_node, true);
9309 case IrBinOpCmpEq:
9310 case IrBinOpCmpGreaterOrEq:
9311 case IrBinOpCmpGreaterThan:
9312 return ir_const_bool(ira, scope, source_node, false);
9313 default:
9314 break;
9315 }
9316 }
9317 }
9318 if (have_op2_cmp_zero && op1_scalar_type->id == ZigTypeIdInt && !op1_scalar_type->data.integral.is_signed) {
9319 if (op2_cmp_zero == CmpEQ) {
9320 // unsigned_x < 0 // false
9321 // unsigned_x >= 0 // true
9322 switch (op_id) {
9323 case IrBinOpCmpLessThan:
9324 return ir_const_bool(ira, scope, source_node, false);
9325 case IrBinOpCmpGreaterOrEq:
9326 return ir_const_bool(ira, scope, source_node, true);
9327 default:
9328 break;
9329 }
9330 } else if (op2_cmp_zero == CmpLT) {
9331 // unsigned_x != -1 // true
9332 // unsigned_x >= -1 // true
9333 // unsigned_x > -1 // true
9334 // unsigned_x == -1 // false
9335 // unsigned_x < -1 // false
9336 // unsigned_x <= -1 // false
9337 switch (op_id) {
9338 case IrBinOpCmpNotEq:
9339 case IrBinOpCmpGreaterOrEq:
9340 case IrBinOpCmpGreaterThan:
9341 return ir_const_bool(ira, scope, source_node, true);
9342 case IrBinOpCmpEq:
9343 case IrBinOpCmpLessThan:
9344 case IrBinOpCmpLessOrEq:
9345 return ir_const_bool(ira, scope, source_node, false);
9346 default:
9347 break;
9348 }
9349 }
9350 }
9351
9352 // It must be a runtime comparison.
9353 // For floats, emit a float comparison instruction.
9354 bool op1_is_float = op1_scalar_type->id == ZigTypeIdFloat || op1_scalar_type->id == ZigTypeIdComptimeFloat;
9355 bool op2_is_float = op2_scalar_type->id == ZigTypeIdFloat || op2_scalar_type->id == ZigTypeIdComptimeFloat;
9356 if (op1_is_float && op2_is_float) {
9357 // Implicit cast the smaller one to the larger one.
9358 ZigType *dest_scalar_type;
9359 if (op1_scalar_type->id == ZigTypeIdComptimeFloat) {
9360 dest_scalar_type = op2_scalar_type;
9361 } else if (op2_scalar_type->id == ZigTypeIdComptimeFloat) {
9362 dest_scalar_type = op1_scalar_type;
9363 } else if (op1_scalar_type->data.floating.bit_count >= op2_scalar_type->data.floating.bit_count) {
9364 dest_scalar_type = op1_scalar_type;
9365 } else {
9366 dest_scalar_type = op2_scalar_type;
9367 }
9368 ZigType *dest_type = (result_type->id == ZigTypeIdVector) ?
9369 get_vector_type(ira->codegen, result_type->data.vector.len, dest_scalar_type) : dest_scalar_type;
9370 Stage1AirInst *casted_op1 = ir_implicit_cast(ira, op1, dest_type);
9371 Stage1AirInst *casted_op2 = ir_implicit_cast(ira, op2, dest_type);
9372 if (type_is_invalid(casted_op1->value->type) || type_is_invalid(casted_op2->value->type))
9373 return ira->codegen->invalid_inst_gen;
9374 return ir_build_bin_op_gen(ira, scope, source_node, result_type, op_id, casted_op1, casted_op2, true);
9375 }
9376
9377 // For mixed unsigned integer sizes, implicit cast both operands to the larger integer.
9378 // For mixed signed and unsigned integers, implicit cast both operands to a signed
9379 // integer with + 1 bit.
9380 // For mixed floats and integers, extract the integer part from the float, cast that to
9381 // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float,
9382 // add/subtract 1.
9383 bool dest_int_is_signed = false;
9384 if (have_op1_cmp_zero) {
9385 if (op1_cmp_zero == CmpLT) dest_int_is_signed = true;
9386 } else if (op1_is_float) {
9387 dest_int_is_signed = true;
9388 } else if (op1_scalar_type->id == ZigTypeIdInt && op1_scalar_type->data.integral.is_signed) {
9389 dest_int_is_signed = true;
9390 }
9391 if (have_op2_cmp_zero) {
9392 if (op2_cmp_zero == CmpLT) dest_int_is_signed = true;
9393 } else if (op2_is_float) {
9394 dest_int_is_signed = true;
9395 } else if (op2->value->type->id == ZigTypeIdInt && op2->value->type->data.integral.is_signed) {
9396 dest_int_is_signed = true;
9397 }
9398 ZigType *dest_float_type = nullptr;
9399 uint32_t op1_bits;
9400 if (instr_is_comptime(op1) && result_type->id != ZigTypeIdVector) {
9401 ZigValue *op1_val = ir_resolve_const(ira, op1, UndefOk);
9402 if (op1_val == nullptr)
9403 return ira->codegen->invalid_inst_gen;
9404 if (op1_val->special == ConstValSpecialUndef)
9405 return ir_const_undef(ira, scope, source_node, ira->codegen->builtin_types.entry_bool);
9406 bool is_unsigned;
9407 if (op1_is_float) {
9408 BigInt bigint = {};
9409 float_init_bigint(&bigint, op1_val);
9410 Cmp zcmp = float_cmp_zero(op1_val);
9411 if (float_has_fraction(op1_val)) {
9412 if (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq) {
9413 return ir_const_bool(ira, scope, source_node, op_id == IrBinOpCmpNotEq);
9414 }
9415 if (zcmp == CmpLT) {
9416 bigint_decr(&bigint);
9417 } else {
9418 bigint_incr(&bigint);
9419 }
9420 }
9421 op1_bits = bigint_bits_needed(&bigint);
9422 is_unsigned = zcmp != CmpLT;
9423 } else {
9424 op1_bits = bigint_bits_needed(&op1_val->data.x_bigint);
9425 is_unsigned = bigint_cmp_zero(&op1_val->data.x_bigint) != CmpLT;
9426 }
9427 if (is_unsigned && dest_int_is_signed) {
9428 op1_bits += 1;
9429 }
9430 } else if (op1_is_float) {
9431 src_assert(op1_scalar_type->id == ZigTypeIdFloat, source_node);
9432 dest_float_type = op1_scalar_type;
9433 } else {
9434 src_assert(op1_scalar_type->id == ZigTypeIdInt, source_node);
9435 op1_bits = op1_scalar_type->data.integral.bit_count;
9436 if (!op1_scalar_type->data.integral.is_signed && dest_int_is_signed) {
9437 op1_bits += 1;
9438 }
9439 }
9440 uint32_t op2_bits;
9441 if (instr_is_comptime(op2) && result_type->id != ZigTypeIdVector) {
9442 ZigValue *op2_val = ir_resolve_const(ira, op2, UndefOk);
9443 if (op2_val == nullptr)
9444 return ira->codegen->invalid_inst_gen;
9445 if (op2_val->special == ConstValSpecialUndef)
9446 return ir_const_undef(ira, scope, source_node, ira->codegen->builtin_types.entry_bool);
9447 bool is_unsigned;
9448 if (op2_is_float) {
9449 BigInt bigint = {};
9450 float_init_bigint(&bigint, op2_val);
9451 Cmp zcmp = float_cmp_zero(op2_val);
9452 if (float_has_fraction(op2_val)) {
9453 if (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq) {
9454 return ir_const_bool(ira, scope, source_node, op_id == IrBinOpCmpNotEq);
9455 }
9456 if (zcmp == CmpLT) {
9457 bigint_decr(&bigint);
9458 } else {
9459 bigint_incr(&bigint);
9460 }
9461 }
9462 op2_bits = bigint_bits_needed(&bigint);
9463 is_unsigned = zcmp != CmpLT;
9464 } else {
9465 op2_bits = bigint_bits_needed(&op2_val->data.x_bigint);
9466 is_unsigned = bigint_cmp_zero(&op2_val->data.x_bigint) != CmpLT;
9467 }
9468 if (is_unsigned && dest_int_is_signed) {
9469 op2_bits += 1;
9470 }
9471 } else if (op2_is_float) {
9472 src_assert(op2_scalar_type->id == ZigTypeIdFloat, source_node);
9473 dest_float_type = op2_scalar_type;
9474 } else {
9475 src_assert(op2_scalar_type->id == ZigTypeIdInt, source_node);
9476 op2_bits = op2_scalar_type->data.integral.bit_count;
9477 if (!op2_scalar_type->data.integral.is_signed && dest_int_is_signed) {
9478 op2_bits += 1;
9479 }
9480 }
9481 ZigType *dest_scalar_type = (dest_float_type == nullptr) ?
9482 get_int_type(ira->codegen, dest_int_is_signed, (op1_bits > op2_bits) ? op1_bits : op2_bits) :
9483 dest_float_type;
9484 ZigType *dest_type = (result_type->id == ZigTypeIdVector) ?
9485 get_vector_type(ira->codegen, result_type->data.vector.len, dest_scalar_type) : dest_scalar_type;
9486
9487 Stage1AirInst *casted_op1 = ir_implicit_cast(ira, op1, dest_type);
9488 if (type_is_invalid(casted_op1->value->type))
9489 return ira->codegen->invalid_inst_gen;
9490 Stage1AirInst *casted_op2 = ir_implicit_cast(ira, op2, dest_type);
9491 if (type_is_invalid(casted_op2->value->type))
9492 return ira->codegen->invalid_inst_gen;
9493 return ir_build_bin_op_gen(ira, scope, source_node, result_type, op_id, casted_op1, casted_op2, true);
9494}
9495
9496static bool type_is_self_comparable(ZigType *ty, bool is_equality_cmp) {
9497 if (type_is_numeric(ty)) {
9498 return true;
9499 }
9500 switch (ty->id) {
9501 case ZigTypeIdInvalid:
9502 zig_unreachable();
9503
9504 case ZigTypeIdComptimeFloat:
9505 case ZigTypeIdComptimeInt:
9506 case ZigTypeIdInt:
9507 case ZigTypeIdFloat:
9508 zig_unreachable(); // handled with the type_is_numeric check above
9509
9510 case ZigTypeIdVector:
9511 // Not every case is handled by the type_is_numeric check above,
9512 // vectors of bool trigger this code path
9513 case ZigTypeIdBool:
9514 case ZigTypeIdMetaType:
9515 case ZigTypeIdVoid:
9516 case ZigTypeIdErrorSet:
9517 case ZigTypeIdFn:
9518 case ZigTypeIdOpaque:
9519 case ZigTypeIdBoundFn:
9520 case ZigTypeIdEnum:
9521 case ZigTypeIdEnumLiteral:
9522 case ZigTypeIdAnyFrame:
9523 return is_equality_cmp;
9524
9525 case ZigTypeIdPointer:
9526 return is_equality_cmp || (ty->data.pointer.ptr_len == PtrLenC);
9527
9528 case ZigTypeIdUnreachable:
9529 case ZigTypeIdArray:
9530 case ZigTypeIdStruct:
9531 case ZigTypeIdUndefined:
9532 case ZigTypeIdNull:
9533 case ZigTypeIdErrorUnion:
9534 case ZigTypeIdUnion:
9535 case ZigTypeIdFnFrame:
9536 return false;
9537
9538 case ZigTypeIdOptional:
9539 return is_equality_cmp && get_src_ptr_type(ty) != nullptr;
9540 }
9541 zig_unreachable();
9542}
9543
9544static Stage1AirInst *ir_try_evaluate_cmp_optional_non_optional_const(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *child_type,
9545 Stage1AirInst *optional, Stage1AirInst *non_optional, IrBinOp op_id)
9546{
9547 assert(optional->value->type->id == ZigTypeIdOptional);
9548 assert(optional->value->type->data.maybe.child_type == non_optional->value->type);
9549 assert(non_optional->value->type == child_type);
9550 assert(op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq);
9551
9552 if (instr_is_comptime(optional) && instr_is_comptime(non_optional)) {
9553 ZigValue *optional_val = ir_resolve_const(ira, optional, UndefBad);
9554 if (!optional_val) {
9555 return ira->codegen->invalid_inst_gen;
9556 }
9557
9558 ZigValue *non_optional_val = ir_resolve_const(ira, non_optional, UndefBad);
9559 if (!non_optional_val) {
9560 return ira->codegen->invalid_inst_gen;
9561 }
9562
9563 if (!optional_value_is_null(optional_val)) {
9564 Stage1AirInst *optional_unwrapped = ir_analyze_optional_value_payload_value(ira, scope, source_node, optional, false);
9565 if (type_is_invalid(optional_unwrapped->value->type)) {
9566 return ira->codegen->invalid_inst_gen;
9567 }
9568
9569 Stage1AirInst *ret = ir_try_evaluate_bin_op_cmp_const(ira, scope, source_node, optional_unwrapped, non_optional, child_type, op_id);
9570 assert(ret != nullptr);
9571 return ret;
9572 }
9573 return ir_const_bool(ira, scope, source_node, (op_id != IrBinOpCmpEq));
9574 } else {
9575 return nullptr;
9576 }
9577}
9578
9579static Stage1AirInst *ir_evaluate_cmp_optional_non_optional(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *child_type,
9580 Stage1AirInst *optional, Stage1AirInst *non_optional, IrBinOp op_id)
9581{
9582 assert(optional->value->type->id == ZigTypeIdOptional);
9583 assert(optional->value->type->data.maybe.child_type == non_optional->value->type);
9584 assert(non_optional->value->type == child_type);
9585 assert(op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq);
9586
9587 ZigType *result_type = ira->codegen->builtin_types.entry_bool;
9588 ir_append_basic_block_gen(&ira->new_irb, ira->new_irb.current_basic_block);
9589
9590 Stage1AirBasicBlock *null_block = ir_create_basic_block_gen(ira, scope, "CmpOptionalNonOptionalOptionalNull");
9591 Stage1AirBasicBlock *non_null_block = ir_create_basic_block_gen(ira, scope, "CmpOptionalNonOptionalOptionalNotNull");
9592 Stage1AirBasicBlock *end_block = ir_create_basic_block_gen(ira, scope, "CmpOptionalNonOptionalEnd");
9593
9594 Stage1AirInst *is_non_null = ir_build_test_non_null_gen(ira, scope, source_node, optional);
9595 ir_build_cond_br_gen(ira, scope, source_node, is_non_null, non_null_block, null_block);
9596
9597 ir_set_cursor_at_end_and_append_block_gen(&ira->new_irb, non_null_block);
9598 Stage1AirInst *optional_unwrapped = ir_analyze_optional_value_payload_value(ira, scope, source_node, optional, false);
9599 if (type_is_invalid(optional_unwrapped->value->type)) {
9600 return ira->codegen->invalid_inst_gen;
9601 }
9602 Stage1AirInst *non_null_cmp_result = ir_build_bin_op_gen(ira, scope, source_node, result_type, op_id,
9603 optional_unwrapped, non_optional, false); // safety check unnecessary for comparison operators
9604 ir_build_br_gen(ira, scope, source_node, end_block);
9605
9606
9607 ir_set_cursor_at_end_and_append_block_gen(&ira->new_irb, null_block);
9608 Stage1AirInst *null_result = ir_const_bool(ira, scope, source_node, (op_id != IrBinOpCmpEq));
9609 ir_build_br_gen(ira, scope, source_node, end_block);
9610
9611 ir_set_cursor_at_end_gen(&ira->new_irb, end_block);
9612 int incoming_count = 2;
9613 Stage1AirBasicBlock **incoming_blocks = heap::c_allocator.allocate_nonzero<Stage1AirBasicBlock *>(incoming_count);
9614 incoming_blocks[0] = null_block;
9615 incoming_blocks[1] = non_null_block;
9616 Stage1AirInst **incoming_values = heap::c_allocator.allocate_nonzero<Stage1AirInst *>(incoming_count);
9617 incoming_values[0] = null_result;
9618 incoming_values[1] = non_null_cmp_result;
9619
9620 const bool merge_comptime = false;
9621 return ir_build_phi_gen(ira, scope, source_node, merge_comptime, incoming_count, incoming_blocks, incoming_values, result_type);
9622}
9623
9624static Stage1AirInst *ir_analyze_cmp_optional_non_optional(IrAnalyze *ira, Scope *scope, AstNode *source_node,
9625 Stage1AirInst *op1, Stage1AirInst *op2, Stage1AirInst *optional, IrBinOp op_id)
9626{
9627 assert(op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq);
9628 assert(optional->value->type->id == ZigTypeIdOptional);
9629 assert(get_src_ptr_type(optional->value->type) == nullptr);
9630
9631 Stage1AirInst *non_optional;
9632 if (op1 == optional) {
9633 non_optional = op2;
9634 } else if (op2 == optional) {
9635 non_optional = op1;
9636 } else {
9637 zig_unreachable();
9638 }
9639
9640 ZigType *child_type = optional->value->type->data.maybe.child_type;
9641 bool child_type_matches = (child_type == non_optional->value->type);
9642 if (!child_type_matches || !type_is_self_comparable(child_type, true)) {
9643 ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("cannot compare types '%s' and '%s'",
9644 buf_ptr(&op1->value->type->name),
9645 buf_ptr(&op2->value->type->name)));
9646
9647 if (!child_type_matches) {
9648 if (non_optional->value->type->id == ZigTypeIdOptional) {
9649 add_error_note(ira->codegen, msg, source_node, buf_sprintf(
9650 "optional to optional comparison is only supported for optional pointer types"));
9651 } else {
9652 add_error_note(ira->codegen, msg, source_node,
9653 buf_sprintf("optional child type '%s' must be the same as non-optional type '%s'",
9654 buf_ptr(&child_type->name),
9655 buf_ptr(&non_optional->value->type->name)));
9656 }
9657 } else {
9658 add_error_note(ira->codegen, msg, source_node,
9659 buf_sprintf("operator not supported for type '%s'",
9660 buf_ptr(&child_type->name)));
9661 }
9662 return ira->codegen->invalid_inst_gen;
9663 }
9664
9665 if (child_type->id == ZigTypeIdVector) {
9666 ir_add_error_node(ira, source_node, buf_sprintf("TODO add comparison of optional vector"));
9667 return ira->codegen->invalid_inst_gen;
9668 }
9669
9670 if (Stage1AirInst *const_result = ir_try_evaluate_cmp_optional_non_optional_const(ira, scope, source_node, child_type,
9671 optional, non_optional, op_id))
9672 {
9673 return const_result;
9674 }
9675
9676 return ir_evaluate_cmp_optional_non_optional(ira, scope, source_node, child_type, optional, non_optional, op_id);
9677}
9678
9679static Stage1AirInst *ir_analyze_bin_op_cmp(IrAnalyze *ira, Stage1ZirInstBinOp *bin_op_instruction) {
9680 Stage1AirInst *op1 = bin_op_instruction->op1->child;
9681 if (type_is_invalid(op1->value->type))
9682 return ira->codegen->invalid_inst_gen;
9683
9684 Stage1AirInst *op2 = bin_op_instruction->op2->child;
9685 if (type_is_invalid(op2->value->type))
9686 return ira->codegen->invalid_inst_gen;
9687
9688 AstNode *source_node = bin_op_instruction->base.source_node;
9689
9690 IrBinOp op_id = bin_op_instruction->op_id;
9691 bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq);
9692 if (is_equality_cmp && op1->value->type->id == ZigTypeIdNull && op2->value->type->id == ZigTypeIdNull) {
9693 return ir_const_bool(ira, bin_op_instruction->base.scope,
9694 bin_op_instruction->base.source_node, (op_id == IrBinOpCmpEq));
9695 } else if (is_equality_cmp &&
9696 ((op1->value->type->id == ZigTypeIdNull && op2->value->type->id == ZigTypeIdOptional) ||
9697 (op2->value->type->id == ZigTypeIdNull && op1->value->type->id == ZigTypeIdOptional)))
9698 {
9699 Stage1AirInst *maybe_op;
9700 if (op1->value->type->id == ZigTypeIdNull) {
9701 maybe_op = op2;
9702 } else if (op2->value->type->id == ZigTypeIdNull) {
9703 maybe_op = op1;
9704 } else {
9705 zig_unreachable();
9706 }
9707 if (instr_is_comptime(maybe_op)) {
9708 ZigValue *maybe_val = ir_resolve_const(ira, maybe_op, UndefBad);
9709 if (!maybe_val)
9710 return ira->codegen->invalid_inst_gen;
9711 bool is_null = optional_value_is_null(maybe_val);
9712 bool bool_result = (op_id == IrBinOpCmpEq) ? is_null : !is_null;
9713 return ir_const_bool(ira, bin_op_instruction->base.scope,
9714 bin_op_instruction->base.source_node, bool_result);
9715 }
9716
9717 Stage1AirInst *is_non_null = ir_build_test_non_null_gen(ira, bin_op_instruction->base.scope,
9718 bin_op_instruction->base.source_node, maybe_op);
9719
9720 if (op_id == IrBinOpCmpEq) {
9721 return ir_build_bool_not_gen(ira, bin_op_instruction->base.scope,
9722 bin_op_instruction->base.source_node, is_non_null);
9723 } else {
9724 return is_non_null;
9725 }
9726 } else if (is_equality_cmp &&
9727 ((op1->value->type->id == ZigTypeIdNull && op2->value->type->id == ZigTypeIdPointer &&
9728 op2->value->type->data.pointer.ptr_len == PtrLenC) ||
9729 (op2->value->type->id == ZigTypeIdNull && op1->value->type->id == ZigTypeIdPointer &&
9730 op1->value->type->data.pointer.ptr_len == PtrLenC)))
9731 {
9732 Stage1AirInst *c_ptr_op;
9733 if (op1->value->type->id == ZigTypeIdNull) {
9734 c_ptr_op = op2;
9735 } else if (op2->value->type->id == ZigTypeIdNull) {
9736 c_ptr_op = op1;
9737 } else {
9738 zig_unreachable();
9739 }
9740 if (instr_is_comptime(c_ptr_op)) {
9741 ZigValue *c_ptr_val = ir_resolve_const(ira, c_ptr_op, UndefOk);
9742 if (!c_ptr_val)
9743 return ira->codegen->invalid_inst_gen;
9744 if (c_ptr_val->special == ConstValSpecialUndef)
9745 return ir_const_undef(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, ira->codegen->builtin_types.entry_bool);
9746 bool is_null = c_ptr_val->data.x_ptr.special == ConstPtrSpecialNull ||
9747 (c_ptr_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
9748 c_ptr_val->data.x_ptr.data.hard_coded_addr.addr == 0);
9749 bool bool_result = (op_id == IrBinOpCmpEq) ? is_null : !is_null;
9750 return ir_const_bool(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, bool_result);
9751 }
9752 Stage1AirInst *is_non_null = ir_build_test_non_null_gen(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, c_ptr_op);
9753
9754 if (op_id == IrBinOpCmpEq) {
9755 return ir_build_bool_not_gen(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, is_non_null);
9756 } else {
9757 return is_non_null;
9758 }
9759 } else if (is_equality_cmp &&
9760 (op1->value->type->id == ZigTypeIdOptional && get_src_ptr_type(op1->value->type) == nullptr))
9761 {
9762 return ir_analyze_cmp_optional_non_optional(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, op1, op2, op1, op_id);
9763 } else if(is_equality_cmp &&
9764 (op2->value->type->id == ZigTypeIdOptional && get_src_ptr_type(op2->value->type) == nullptr))
9765 {
9766 return ir_analyze_cmp_optional_non_optional(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, op1, op2, op2, op_id);
9767 } else if (op1->value->type->id == ZigTypeIdNull || op2->value->type->id == ZigTypeIdNull) {
9768 ZigType *non_null_type = (op1->value->type->id == ZigTypeIdNull) ? op2->value->type : op1->value->type;
9769 ir_add_error_node(ira, source_node, buf_sprintf("comparison of '%s' with null",
9770 buf_ptr(&non_null_type->name)));
9771 return ira->codegen->invalid_inst_gen;
9772 } else if (is_equality_cmp && (
9773 (op1->value->type->id == ZigTypeIdEnumLiteral && op2->value->type->id == ZigTypeIdUnion) ||
9774 (op2->value->type->id == ZigTypeIdEnumLiteral && op1->value->type->id == ZigTypeIdUnion)))
9775 {
9776 // Support equality comparison between a union's tag value and a enum literal
9777 Stage1AirInst *union_val = op1->value->type->id == ZigTypeIdUnion ? op1 : op2;
9778 Stage1AirInst *enum_val = op1->value->type->id == ZigTypeIdUnion ? op2 : op1;
9779
9780 if (!is_tagged_union(union_val->value->type)) {
9781 ErrorMsg *msg = ir_add_error_node(ira, source_node,
9782 buf_sprintf("comparison of union and enum literal is only valid for tagged union types"));
9783 add_error_note(ira->codegen, msg, union_val->value->type->data.unionation.decl_node,
9784 buf_sprintf("type %s is not a tagged union",
9785 buf_ptr(&union_val->value->type->name)));
9786 return ira->codegen->invalid_inst_gen;
9787 }
9788
9789 ZigType *tag_type = union_val->value->type->data.unionation.tag_type;
9790 assert(tag_type != nullptr);
9791
9792 Stage1AirInst *casted_union = ir_implicit_cast(ira, union_val, tag_type);
9793 if (type_is_invalid(casted_union->value->type))
9794 return ira->codegen->invalid_inst_gen;
9795
9796 Stage1AirInst *casted_val = ir_implicit_cast(ira, enum_val, tag_type);
9797 if (type_is_invalid(casted_val->value->type))
9798 return ira->codegen->invalid_inst_gen;
9799
9800 if (instr_is_comptime(casted_union)) {
9801 ZigValue *const_union_val = ir_resolve_const(ira, casted_union, UndefBad);
9802 if (!const_union_val)
9803 return ira->codegen->invalid_inst_gen;
9804
9805 ZigValue *const_enum_val = ir_resolve_const(ira, casted_val, UndefBad);
9806 if (!const_enum_val)
9807 return ira->codegen->invalid_inst_gen;
9808
9809 Cmp cmp_result = bigint_cmp(&const_union_val->data.x_union.tag, &const_enum_val->data.x_enum_tag);
9810 bool bool_result = (op_id == IrBinOpCmpEq) ? cmp_result == CmpEQ : cmp_result != CmpEQ;
9811
9812 return ir_const_bool(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, bool_result);
9813 }
9814
9815 return ir_build_bin_op_gen(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, ira->codegen->builtin_types.entry_bool,
9816 op_id, casted_union, casted_val, bin_op_instruction->safety_check_on);
9817 }
9818
9819 if (op1->value->type->id == ZigTypeIdErrorSet && op2->value->type->id == ZigTypeIdErrorSet) {
9820 if (!is_equality_cmp) {
9821 ir_add_error_node(ira, source_node, buf_sprintf("operator not allowed for errors"));
9822 return ira->codegen->invalid_inst_gen;
9823 }
9824 ZigType *intersect_type = get_error_set_intersection(ira, op1->value->type, op2->value->type, source_node);
9825 if (type_is_invalid(intersect_type)) {
9826 return ira->codegen->invalid_inst_gen;
9827 }
9828
9829 if (!resolve_inferred_error_set(ira->codegen, intersect_type, source_node)) {
9830 return ira->codegen->invalid_inst_gen;
9831 }
9832
9833 // exception if one of the operators has the type of the empty error set, we allow the comparison
9834 // (and make it comptime known)
9835 // this is a function which is evaluated at comptime and returns an inferred error set will have an empty
9836 // error set.
9837 if (op1->value->type->data.error_set.err_count == 0 || op2->value->type->data.error_set.err_count == 0) {
9838 bool are_equal = false;
9839 bool answer;
9840 if (op_id == IrBinOpCmpEq) {
9841 answer = are_equal;
9842 } else if (op_id == IrBinOpCmpNotEq) {
9843 answer = !are_equal;
9844 } else {
9845 zig_unreachable();
9846 }
9847 return ir_const_bool(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, answer);
9848 }
9849
9850 if (!type_is_global_error_set(intersect_type)) {
9851 if (intersect_type->data.error_set.err_count == 0) {
9852 ir_add_error_node(ira, source_node,
9853 buf_sprintf("error sets '%s' and '%s' have no common errors",
9854 buf_ptr(&op1->value->type->name), buf_ptr(&op2->value->type->name)));
9855 return ira->codegen->invalid_inst_gen;
9856 }
9857 if (op1->value->type->data.error_set.err_count == 1 && op2->value->type->data.error_set.err_count == 1) {
9858 bool are_equal = true;
9859 bool answer;
9860 if (op_id == IrBinOpCmpEq) {
9861 answer = are_equal;
9862 } else if (op_id == IrBinOpCmpNotEq) {
9863 answer = !are_equal;
9864 } else {
9865 zig_unreachable();
9866 }
9867 return ir_const_bool(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, answer);
9868 }
9869 }
9870
9871 if (instr_is_comptime(op1) && instr_is_comptime(op2)) {
9872 ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad);
9873 if (op1_val == nullptr)
9874 return ira->codegen->invalid_inst_gen;
9875 ZigValue *op2_val = ir_resolve_const(ira, op2, UndefBad);
9876 if (op2_val == nullptr)
9877 return ira->codegen->invalid_inst_gen;
9878
9879 bool answer;
9880 bool are_equal = op1_val->data.x_err_set->value == op2_val->data.x_err_set->value;
9881 if (op_id == IrBinOpCmpEq) {
9882 answer = are_equal;
9883 } else if (op_id == IrBinOpCmpNotEq) {
9884 answer = !are_equal;
9885 } else {
9886 zig_unreachable();
9887 }
9888
9889 return ir_const_bool(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, answer);
9890 }
9891
9892 return ir_build_bin_op_gen(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, ira->codegen->builtin_types.entry_bool,
9893 op_id, op1, op2, bin_op_instruction->safety_check_on);
9894 }
9895
9896 if (type_is_numeric(op1->value->type) && type_is_numeric(op2->value->type)) {
9897 // This operation allows any combination of integer and float types, regardless of the
9898 // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for
9899 // numeric types.
9900 return ir_analyze_bin_op_cmp_numeric(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, op1, op2, op_id);
9901 }
9902
9903 Stage1AirInst *instructions[] = {op1, op2};
9904 ZigType *resolved_type = ir_resolve_peer_types(ira, source_node, nullptr, instructions, 2);
9905 if (type_is_invalid(resolved_type))
9906 return ira->codegen->invalid_inst_gen;
9907
9908 bool operator_allowed = type_is_self_comparable(resolved_type, is_equality_cmp);
9909
9910 if (!operator_allowed) {
9911 ir_add_error_node(ira, source_node,
9912 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
9913 return ira->codegen->invalid_inst_gen;
9914 }
9915
9916 Stage1AirInst *casted_op1 = ir_implicit_cast(ira, op1, resolved_type);
9917 if (type_is_invalid(casted_op1->value->type))
9918 return ira->codegen->invalid_inst_gen;
9919
9920 Stage1AirInst *casted_op2 = ir_implicit_cast(ira, op2, resolved_type);
9921 if (type_is_invalid(casted_op2->value->type))
9922 return ira->codegen->invalid_inst_gen;
9923
9924 Stage1AirInst *resolve_const_result = ir_try_evaluate_bin_op_cmp_const(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, casted_op1,
9925 casted_op2, resolved_type, op_id);
9926 if (resolve_const_result != nullptr) {
9927 return resolve_const_result;
9928 }
9929
9930 ZigType *res_type = (resolved_type->id == ZigTypeIdVector) ?
9931 get_vector_type(ira->codegen, resolved_type->data.vector.len, ira->codegen->builtin_types.entry_bool) :
9932 ira->codegen->builtin_types.entry_bool;
9933 return ir_build_bin_op_gen(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, res_type,
9934 op_id, casted_op1, casted_op2, bin_op_instruction->safety_check_on);
9935}
9936
9937static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *type_entry,
9938 ZigValue *op1_val, IrBinOp op_id, ZigValue *op2_val, ZigValue *out_val)
9939{
9940 bool is_int;
9941 bool is_float;
9942 Cmp op2_zcmp;
9943 if (type_entry->id == ZigTypeIdInt || type_entry->id == ZigTypeIdComptimeInt) {
9944 is_int = true;
9945 is_float = false;
9946 op2_zcmp = bigint_cmp_zero(&op2_val->data.x_bigint);
9947 } else if (type_entry->id == ZigTypeIdFloat ||
9948 type_entry->id == ZigTypeIdComptimeFloat)
9949 {
9950 is_int = false;
9951 is_float = true;
9952 op2_zcmp = float_cmp_zero(op2_val);
9953 } else {
9954 zig_unreachable();
9955 }
9956
9957 if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod ||
9958 op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ)
9959 {
9960 return ir_add_error_node(ira, source_node, buf_sprintf("division by zero"));
9961 }
9962 if ((op_id == IrBinOpRemRem || op_id == IrBinOpRemMod) && op2_zcmp == CmpLT) {
9963 return ir_add_error_node(ira, source_node, buf_sprintf("negative denominator"));
9964 }
9965
9966 switch (op_id) {
9967 case IrBinOpInvalid:
9968 case IrBinOpBoolOr:
9969 case IrBinOpBoolAnd:
9970 case IrBinOpCmpEq:
9971 case IrBinOpCmpNotEq:
9972 case IrBinOpCmpLessThan:
9973 case IrBinOpCmpGreaterThan:
9974 case IrBinOpCmpLessOrEq:
9975 case IrBinOpCmpGreaterOrEq:
9976 case IrBinOpArrayCat:
9977 case IrBinOpArrayMult:
9978 case IrBinOpRemUnspecified:
9979 zig_unreachable();
9980 case IrBinOpBinOr:
9981 assert(is_int);
9982 bigint_or(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
9983 break;
9984 case IrBinOpBinXor:
9985 assert(is_int);
9986 bigint_xor(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
9987 break;
9988 case IrBinOpBinAnd:
9989 assert(is_int);
9990 bigint_and(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
9991 break;
9992 case IrBinOpBitShiftLeftExact:
9993 assert(is_int);
9994 bigint_shl(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
9995 break;
9996 case IrBinOpBitShiftLeftLossy:
9997 assert(type_entry->id == ZigTypeIdInt);
9998 bigint_shl_trunc(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint,
9999 type_entry->data.integral.bit_count, type_entry->data.integral.is_signed);
10000 break;
10001 case IrBinOpBitShiftRightExact:
10002 {
10003 assert(is_int);
10004 bigint_shr(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
10005 BigInt orig_bigint;
10006 bigint_shl(&orig_bigint, &out_val->data.x_bigint, &op2_val->data.x_bigint);
10007 if (bigint_cmp(&op1_val->data.x_bigint, &orig_bigint) != CmpEQ) {
10008 return ir_add_error_node(ira, source_node, buf_sprintf("exact shift shifted out 1 bits"));
10009 }
10010 break;
10011 }
10012 case IrBinOpBitShiftRightLossy:
10013 assert(is_int);
10014 bigint_shr(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
10015 break;
10016 case IrBinOpAdd:
10017 if (is_int) {
10018 bigint_add(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
10019 } else {
10020 float_add(out_val, op1_val, op2_val);
10021 }
10022 break;
10023 case IrBinOpAddWrap:
10024 assert(type_entry->id == ZigTypeIdInt);
10025 bigint_add_wrap(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint,
10026 type_entry->data.integral.bit_count, type_entry->data.integral.is_signed);
10027 break;
10028 case IrBinOpSub:
10029 if (is_int) {
10030 bigint_sub(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
10031 } else {
10032 float_sub(out_val, op1_val, op2_val);
10033 }
10034 break;
10035 case IrBinOpSubWrap:
10036 assert(type_entry->id == ZigTypeIdInt);
10037 bigint_sub_wrap(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint,
10038 type_entry->data.integral.bit_count, type_entry->data.integral.is_signed);
10039 break;
10040 case IrBinOpMult:
10041 if (is_int) {
10042 bigint_mul(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
10043 } else {
10044 float_mul(out_val, op1_val, op2_val);
10045 }
10046 break;
10047 case IrBinOpMultWrap:
10048 assert(type_entry->id == ZigTypeIdInt);
10049 bigint_mul_wrap(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint,
10050 type_entry->data.integral.bit_count, type_entry->data.integral.is_signed);
10051 break;
10052 case IrBinOpDivUnspecified:
10053 assert(is_float);
10054 float_div(out_val, op1_val, op2_val);
10055 break;
10056 case IrBinOpDivTrunc:
10057 if (is_int) {
10058 bigint_div_trunc(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
10059 } else {
10060 float_div_trunc(out_val, op1_val, op2_val);
10061 }
10062 break;
10063 case IrBinOpDivFloor:
10064 if (is_int) {
10065 bigint_div_floor(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
10066 } else {
10067 float_div_floor(out_val, op1_val, op2_val);
10068 }
10069 break;
10070 case IrBinOpDivExact:
10071 if (is_int) {
10072 bigint_div_trunc(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
10073 BigInt remainder;
10074 bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
10075 if (bigint_cmp_zero(&remainder) != CmpEQ) {
10076 return ir_add_error_node(ira, source_node, buf_sprintf("exact division had a remainder"));
10077 }
10078 } else {
10079 float_div_trunc(out_val, op1_val, op2_val);
10080 ZigValue remainder = {};
10081 float_rem(&remainder, op1_val, op2_val);
10082 if (float_cmp_zero(&remainder) != CmpEQ) {
10083 return ir_add_error_node(ira, source_node, buf_sprintf("exact division had a remainder"));
10084 }
10085 }
10086 break;
10087 case IrBinOpRemRem:
10088 if (is_int) {
10089 bigint_rem(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
10090 } else {
10091 float_rem(out_val, op1_val, op2_val);
10092 }
10093 break;
10094 case IrBinOpRemMod:
10095 if (is_int) {
10096 bigint_mod(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
10097 } else {
10098 float_mod(out_val, op1_val, op2_val);
10099 }
10100 break;
10101 case IrBinOpMax:
10102 if (is_int) {
10103 bigint_max(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
10104 } else {
10105 float_max(out_val, op1_val, op2_val);
10106 }
10107 break;
10108 case IrBinOpMin:
10109 if (is_int) {
10110 bigint_min(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
10111 } else {
10112 float_min(out_val, op1_val, op2_val);
10113 }
10114 break;
10115 case IrBinOpAddSat:
10116 if (is_int) {
10117 bigint_add_sat(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint, type_entry->data.integral.bit_count, type_entry->data.integral.is_signed);
10118 } else {
10119 zig_unreachable();
10120 }
10121 break;
10122 case IrBinOpSubSat:
10123 if (is_int) {
10124 bigint_sub_sat(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint, type_entry->data.integral.bit_count, type_entry->data.integral.is_signed);
10125 } else {
10126 zig_unreachable();
10127 }
10128 break;
10129 case IrBinOpMultSat:
10130 if (is_int) {
10131 bigint_mul_sat(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint, type_entry->data.integral.bit_count, type_entry->data.integral.is_signed);
10132 } else {
10133 zig_unreachable();
10134 }
10135 break;
10136 case IrBinOpShlSat:
10137 if (is_int) {
10138 bigint_shl_sat(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint, type_entry->data.integral.bit_count, type_entry->data.integral.is_signed);
10139 } else {
10140 zig_unreachable();
10141 }
10142 break;
10143 }
10144
10145 if (type_entry->id == ZigTypeIdInt) {
10146 if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count,
10147 type_entry->data.integral.is_signed))
10148 {
10149 return ir_add_error_node(ira, source_node, buf_sprintf("operation caused overflow"));
10150 }
10151 }
10152
10153 out_val->type = type_entry;
10154 out_val->special = ConstValSpecialStatic;
10155 return nullptr;
10156}
10157
10158// This works on operands that have already been checked to be comptime known.
10159static Stage1AirInst *ir_analyze_math_op(IrAnalyze *ira, Scope *scope, AstNode *source_node,
10160 ZigType *type_entry, ZigValue *op1_val, IrBinOp op_id, ZigValue *op2_val)
10161{
10162 Stage1AirInst *result_instruction = ir_const(ira, scope, source_node, type_entry);
10163 ZigValue *out_val = result_instruction->value;
10164 if (type_entry->id == ZigTypeIdVector) {
10165 expand_undef_array(ira->codegen, op1_val);
10166 expand_undef_array(ira->codegen, op2_val);
10167 out_val->special = ConstValSpecialUndef;
10168 expand_undef_array(ira->codegen, out_val);
10169 size_t len = type_entry->data.vector.len;
10170 ZigType *scalar_type = type_entry->data.vector.elem_type;
10171 for (size_t i = 0; i < len; i += 1) {
10172 ZigValue *scalar_op1_val = &op1_val->data.x_array.data.s_none.elements[i];
10173 ZigValue *scalar_op2_val = &op2_val->data.x_array.data.s_none.elements[i];
10174 ZigValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i];
10175 assert(scalar_op1_val->type == scalar_type);
10176 assert(scalar_out_val->type == scalar_type);
10177 ErrorMsg *msg = ir_eval_math_op_scalar(ira, scope, source_node, scalar_type,
10178 scalar_op1_val, op_id, scalar_op2_val, scalar_out_val);
10179 if (msg != nullptr) {
10180 add_error_note(ira->codegen, msg, source_node,
10181 buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i));
10182 return ira->codegen->invalid_inst_gen;
10183 }
10184 }
10185 out_val->type = type_entry;
10186 out_val->special = ConstValSpecialStatic;
10187 } else {
10188 if (ir_eval_math_op_scalar(ira, scope, source_node, type_entry, op1_val, op_id, op2_val, out_val) != nullptr) {
10189 return ira->codegen->invalid_inst_gen;
10190 }
10191 }
10192 return ir_implicit_cast(ira, result_instruction, type_entry);
10193}
10194
10195static Stage1AirInst *ir_analyze_truncate(IrAnalyze *ira, Scope *scope, AstNode *source_node,
10196 ZigType *dest_scalar_type, AstNode *dest_type_node,
10197 Stage1AirInst *operand, AstNode *operand_node)
10198{
10199 if (dest_scalar_type->id != ZigTypeIdInt &&
10200 dest_scalar_type->id != ZigTypeIdComptimeInt)
10201 {
10202 ir_add_error_node(ira, dest_type_node,
10203 buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_scalar_type->name)));
10204 return ira->codegen->invalid_inst_gen;
10205 }
10206
10207 ZigType *src_type = operand->value->type;
10208 bool is_vector = (src_type->id == ZigTypeIdVector);
10209 ZigType *src_scalar_type = is_vector ?
10210 src_type->data.vector.elem_type : src_type;
10211
10212 ZigType *dest_type = is_vector ?
10213 get_vector_type(ira->codegen, src_type->data.vector.len, dest_scalar_type) :
10214 dest_scalar_type;
10215
10216 if (src_scalar_type->id != ZigTypeIdInt && src_scalar_type->id != ZigTypeIdComptimeInt) {
10217 ir_add_error_node(ira, operand_node,
10218 buf_sprintf("expected integer type, found '%s'", buf_ptr(&src_scalar_type->name)));
10219 return ira->codegen->invalid_inst_gen;
10220 }
10221
10222 if (dest_scalar_type->id == ZigTypeIdComptimeInt) {
10223 return ir_implicit_cast2(ira, scope, operand_node, operand, dest_type);
10224 }
10225
10226 if (src_scalar_type->id != ZigTypeIdComptimeInt) {
10227 if (src_scalar_type->data.integral.is_signed != dest_scalar_type->data.integral.is_signed) {
10228 const char *sign_str = dest_scalar_type->data.integral.is_signed ? "signed" : "unsigned";
10229 ir_add_error_node(ira, operand_node, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_scalar_type->name)));
10230 return ira->codegen->invalid_inst_gen;
10231 } else if (src_scalar_type->data.integral.bit_count > 0 && src_scalar_type->data.integral.bit_count < dest_scalar_type->data.integral.bit_count) {
10232 ir_add_error_node(ira, operand_node, buf_sprintf("type '%s' has fewer bits than destination type '%s'",
10233 buf_ptr(&src_scalar_type->name), buf_ptr(&dest_scalar_type->name)));
10234 return ira->codegen->invalid_inst_gen;
10235 }
10236 }
10237
10238 if (instr_is_comptime(operand)) {
10239 ZigValue *val = ir_resolve_const(ira, operand, UndefBad);
10240 if (val == nullptr)
10241 return ira->codegen->invalid_inst_gen;
10242
10243 if (!is_vector) {
10244 Stage1AirInst *result = ir_const(ira, scope, source_node, dest_type);
10245 bigint_truncate(&result->value->data.x_bigint, &val->data.x_bigint,
10246 dest_scalar_type->data.integral.bit_count,
10247 dest_scalar_type->data.integral.is_signed);
10248 return result;
10249 }
10250
10251 Stage1AirInst *result_instruction = ir_const(ira, scope, source_node, dest_type);
10252 ZigValue *out_val = result_instruction->value;
10253 expand_undef_array(ira->codegen, operand->value);
10254 out_val->special = ConstValSpecialUndef;
10255 expand_undef_array(ira->codegen, out_val);
10256 size_t len = dest_type->data.vector.len;
10257 for (size_t i = 0; i < len; i += 1) {
10258 ZigValue *scalar_operand_val = &operand->value->data.x_array.data.s_none.elements[i];
10259 ZigValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i];
10260 assert(scalar_operand_val->type == dest_scalar_type);
10261 assert(scalar_out_val->type == dest_scalar_type);
10262
10263 bigint_truncate(&scalar_out_val->data.x_bigint,
10264 &scalar_operand_val->data.x_bigint,
10265 dest_scalar_type->data.integral.bit_count,
10266 dest_scalar_type->data.integral.is_signed);
10267
10268 scalar_out_val->type = dest_scalar_type;
10269 scalar_out_val->special = ConstValSpecialStatic;
10270 }
10271 out_val->type = dest_type;
10272 out_val->special = ConstValSpecialStatic;
10273 return result_instruction;
10274 }
10275
10276 if (src_scalar_type->data.integral.bit_count == 0 ||
10277 dest_scalar_type->data.integral.bit_count == 0)
10278 {
10279 Stage1AirInst *result = ir_const(ira, scope, source_node, dest_type);
10280 if (!is_vector) {
10281 bigint_init_unsigned(&result->value->data.x_bigint, 0);
10282 }
10283 return result;
10284 }
10285
10286 return ir_build_truncate_gen(ira, scope, source_node, dest_type, operand);
10287}
10288
10289static Stage1AirInst *ir_analyze_bit_shift(IrAnalyze *ira, Stage1ZirInstBinOp *bin_op_instruction) {
10290 Stage1AirInst *op1 = bin_op_instruction->op1->child;
10291 if (type_is_invalid(op1->value->type))
10292 return ira->codegen->invalid_inst_gen;
10293
10294 Stage1AirInst *op2 = bin_op_instruction->op2->child;
10295 if (type_is_invalid(op2->value->type))
10296 return ira->codegen->invalid_inst_gen;
10297
10298 ZigType *op1_type = op1->value->type;
10299 ZigType *op2_type = op2->value->type;
10300
10301 if (op1_type->id == ZigTypeIdVector && op2_type->id != ZigTypeIdVector) {
10302 ir_add_error_node(ira, bin_op_instruction->op1->source_node,
10303 buf_sprintf("bit shifting operation expected vector type, found '%s'",
10304 buf_ptr(&op2_type->name)));
10305 return ira->codegen->invalid_inst_gen;
10306 }
10307
10308 if (op1_type->id != ZigTypeIdVector && op2_type->id == ZigTypeIdVector) {
10309 ir_add_error_node(ira, bin_op_instruction->op1->source_node,
10310 buf_sprintf("bit shifting operation expected vector type, found '%s'",
10311 buf_ptr(&op1_type->name)));
10312 return ira->codegen->invalid_inst_gen;
10313 }
10314
10315 ZigType *op1_scalar_type = (op1_type->id == ZigTypeIdVector) ?
10316 op1_type->data.vector.elem_type : op1_type;
10317 ZigType *op2_scalar_type = (op2_type->id == ZigTypeIdVector) ?
10318 op2_type->data.vector.elem_type : op2_type;
10319
10320 if (op1_scalar_type->id != ZigTypeIdInt && op1_scalar_type->id != ZigTypeIdComptimeInt) {
10321 ir_add_error_node(ira, bin_op_instruction->op1->source_node,
10322 buf_sprintf("bit shifting operation expected integer type, found '%s'",
10323 buf_ptr(&op1_scalar_type->name)));
10324 return ira->codegen->invalid_inst_gen;
10325 }
10326
10327 if (op2_scalar_type->id != ZigTypeIdInt && op2_scalar_type->id != ZigTypeIdComptimeInt) {
10328 ir_add_error_node(ira, bin_op_instruction->op2->source_node,
10329 buf_sprintf("shift amount has to be an integer type, but found '%s'",
10330 buf_ptr(&op2_scalar_type->name)));
10331 return ira->codegen->invalid_inst_gen;
10332 }
10333
10334 Stage1AirInst *casted_op2;
10335 IrBinOp op_id = bin_op_instruction->op_id;
10336 if (op1_scalar_type->id == ZigTypeIdComptimeInt) {
10337 // comptime_int has no finite bit width
10338 casted_op2 = op2;
10339
10340 if (op_id == IrBinOpBitShiftLeftLossy || op_id == IrBinOpShlSat) {
10341 op_id = IrBinOpBitShiftLeftExact;
10342 }
10343
10344 if (!instr_is_comptime(op2)) {
10345 ir_add_error_node(ira, bin_op_instruction->base.source_node,
10346 buf_sprintf("LHS of shift must be a fixed-width integer type, or RHS must be compile-time known"));
10347 return ira->codegen->invalid_inst_gen;
10348 }
10349
10350 ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
10351 if (op2_val == nullptr)
10352 return ira->codegen->invalid_inst_gen;
10353
10354 if (op2_val->data.x_bigint.is_negative) {
10355 Buf *val_buf = buf_alloc();
10356 bigint_append_buf(val_buf, &op2_val->data.x_bigint, 10);
10357 ir_add_error(ira, casted_op2,
10358 buf_sprintf("shift by negative value %s", buf_ptr(val_buf)));
10359 return ira->codegen->invalid_inst_gen;
10360 }
10361 } else if (op_id == IrBinOpShlSat) {
10362 casted_op2 = ir_analyze_truncate(ira,
10363 bin_op_instruction->base.scope, bin_op_instruction->base.source_node,
10364 op1_scalar_type, bin_op_instruction->op1->source_node,
10365 op2, bin_op_instruction->op2->source_node);
10366 if (type_is_invalid(casted_op2->value->type))
10367 return ira->codegen->invalid_inst_gen;
10368 } else {
10369 const unsigned bit_count = op1_scalar_type->data.integral.bit_count;
10370 ZigType *shift_amt_type = get_smallest_unsigned_int_type(ira->codegen,
10371 bit_count > 0 ? bit_count - 1 : 0);
10372
10373 if (op1_type->id == ZigTypeIdVector) {
10374 shift_amt_type = get_vector_type(ira->codegen, op1_type->data.vector.len,
10375 shift_amt_type);
10376 }
10377
10378 casted_op2 = ir_implicit_cast(ira, op2, shift_amt_type);
10379 if (type_is_invalid(casted_op2->value->type))
10380 return ira->codegen->invalid_inst_gen;
10381
10382 // This check is only valid iff op1 has at least one bit
10383 if (bit_count > 0 && instr_is_comptime(casted_op2)) {
10384 ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
10385 if (op2_val == nullptr)
10386 return ira->codegen->invalid_inst_gen;
10387
10388 ZigValue bit_count_value = {};
10389 init_const_usize(ira->codegen, &bit_count_value, bit_count);
10390
10391 if (!value_cmp_numeric_val_all(op2_val, CmpLT, &bit_count_value)) {
10392 ErrorMsg* msg = ir_add_error_node(ira,
10393 bin_op_instruction->base.source_node,
10394 buf_sprintf("RHS of shift is too large for LHS type"));
10395 add_error_note(ira->codegen, msg, op1->source_node,
10396 buf_sprintf("type %s has only %u bits",
10397 buf_ptr(&op1->value->type->name), bit_count));
10398
10399 return ira->codegen->invalid_inst_gen;
10400 }
10401 }
10402 }
10403
10404 // Fast path for zero RHS
10405 if (instr_is_comptime(casted_op2)) {
10406 ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
10407 if (op2_val == nullptr)
10408 return ira->codegen->invalid_inst_gen;
10409
10410 if (op2_val->type->id == ZigTypeIdVector) {
10411 expand_undef_array(ira->codegen, op2_val);
10412 size_t len = op2_val->type->data.vector.len;
10413 for (size_t i = 0; i < len; i += 1) {
10414 ZigValue *scalar_val = &op2_val->data.x_array.data.s_none.elements[i];
10415 if (scalar_val->data.x_bigint.is_negative) {
10416 Buf *val_buf = buf_alloc();
10417 bigint_append_buf(val_buf, &scalar_val->data.x_bigint, 10);
10418 ir_add_error(ira, casted_op2,
10419 buf_sprintf("shift by negative value %s at vector index %zu",
10420 buf_ptr(val_buf), i));
10421 return ira->codegen->invalid_inst_gen;
10422 }
10423 }
10424 } else {
10425 if (op2_val->data.x_bigint.is_negative) {
10426 Buf *val_buf = buf_alloc();
10427 bigint_append_buf(val_buf, &op2_val->data.x_bigint, 10);
10428 ir_add_error(ira, casted_op2,
10429 buf_sprintf("shift by negative value %s", buf_ptr(val_buf)));
10430 return ira->codegen->invalid_inst_gen;
10431 }
10432 }
10433
10434 if (value_cmp_numeric_val_all(op2_val, CmpEQ, nullptr))
10435 return ir_analyze_cast(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, op1->value->type, op1);
10436 }
10437
10438 if (instr_is_comptime(op1) && instr_is_comptime(casted_op2)) {
10439 ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad);
10440 if (op1_val == nullptr)
10441 return ira->codegen->invalid_inst_gen;
10442
10443 ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
10444 if (op2_val == nullptr)
10445 return ira->codegen->invalid_inst_gen;
10446
10447 return ir_analyze_math_op(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, op1_type, op1_val, op_id, op2_val);
10448 }
10449
10450 return ir_build_bin_op_gen(ira,
10451 bin_op_instruction->base.scope, bin_op_instruction->base.source_node,
10452 op1->value->type, op_id, op1, casted_op2, bin_op_instruction->safety_check_on);
10453}
10454
10455static bool ok_float_op(IrBinOp op) {
10456 switch (op) {
10457 case IrBinOpInvalid:
10458 zig_unreachable();
10459 case IrBinOpAdd:
10460 case IrBinOpSub:
10461 case IrBinOpMult:
10462 case IrBinOpDivUnspecified:
10463 case IrBinOpDivTrunc:
10464 case IrBinOpDivFloor:
10465 case IrBinOpDivExact:
10466 case IrBinOpRemRem:
10467 case IrBinOpRemMod:
10468 case IrBinOpRemUnspecified:
10469 case IrBinOpMax:
10470 case IrBinOpMin:
10471 return true;
10472
10473 case IrBinOpBoolOr:
10474 case IrBinOpBoolAnd:
10475 case IrBinOpCmpEq:
10476 case IrBinOpCmpNotEq:
10477 case IrBinOpCmpLessThan:
10478 case IrBinOpCmpGreaterThan:
10479 case IrBinOpCmpLessOrEq:
10480 case IrBinOpCmpGreaterOrEq:
10481 case IrBinOpBinOr:
10482 case IrBinOpBinXor:
10483 case IrBinOpBinAnd:
10484 case IrBinOpBitShiftLeftLossy:
10485 case IrBinOpBitShiftLeftExact:
10486 case IrBinOpBitShiftRightLossy:
10487 case IrBinOpBitShiftRightExact:
10488 case IrBinOpAddWrap:
10489 case IrBinOpSubWrap:
10490 case IrBinOpAddSat:
10491 case IrBinOpSubSat:
10492 case IrBinOpMultSat:
10493 case IrBinOpShlSat:
10494 case IrBinOpMultWrap:
10495 case IrBinOpArrayCat:
10496 case IrBinOpArrayMult:
10497 return false;
10498 }
10499 zig_unreachable();
10500}
10501
10502static IrBinOp map_comptime_arithmetic_op(IrBinOp op) {
10503 switch (op) {
10504 case IrBinOpAddWrap:
10505 case IrBinOpAddSat:
10506 return IrBinOpAdd;
10507
10508 case IrBinOpSubWrap:
10509 case IrBinOpSubSat:
10510 return IrBinOpSub;
10511
10512 case IrBinOpMultWrap:
10513 case IrBinOpMultSat:
10514 return IrBinOpMult;
10515
10516 default:
10517 return op;
10518 }
10519}
10520
10521static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
10522 switch (op) {
10523 case IrBinOpAdd:
10524 case IrBinOpSub:
10525 break;
10526 default:
10527 return false;
10528 }
10529 if (lhs_type->id != ZigTypeIdPointer)
10530 return false;
10531 switch (lhs_type->data.pointer.ptr_len) {
10532 case PtrLenSingle:
10533 return false;
10534 case PtrLenUnknown:
10535 case PtrLenC:
10536 return true;
10537 }
10538 zig_unreachable();
10539}
10540
10541// Returns true if integer `value` can be converted to `type_entry` without
10542// losing data.
10543// If `value` is a vector the function returns true if this is valid for every
10544// element.
10545static bool value_numeric_fits_in_type(ZigValue *value, ZigType *type_entry) {
10546 assert(value->special == ConstValSpecialStatic);
10547 assert(type_entry->id == ZigTypeIdInt);
10548
10549 switch (value->type->id) {
10550 case ZigTypeIdComptimeInt:
10551 case ZigTypeIdInt: {
10552 return bigint_fits_in_bits(&value->data.x_bigint, type_entry->data.integral.bit_count,
10553 type_entry->data.integral.is_signed);
10554 }
10555 case ZigTypeIdVector: {
10556 for (size_t i = 0; i < value->type->data.vector.len; i++) {
10557 ZigValue *scalar_value = &value->data.x_array.data.s_none.elements[i];
10558 const bool result = bigint_fits_in_bits(&scalar_value->data.x_bigint,
10559 type_entry->data.integral.bit_count, type_entry->data.integral.is_signed);
10560 if (!result) return false;
10561 }
10562 return true;
10563 }
10564 default: zig_unreachable();
10565 }
10566}
10567
10568static bool value_cmp_numeric_val(ZigValue *left, Cmp predicate, ZigValue *right, bool any) {
10569 assert(left->special == ConstValSpecialStatic);
10570 assert(right == nullptr || right->special == ConstValSpecialStatic);
10571
10572 switch (left->type->id) {
10573 case ZigTypeIdComptimeInt:
10574 case ZigTypeIdInt: {
10575 const Cmp result = right ?
10576 bigint_cmp(&left->data.x_bigint, &right->data.x_bigint) :
10577 bigint_cmp_zero(&left->data.x_bigint);
10578 return result == predicate;
10579 }
10580 case ZigTypeIdComptimeFloat:
10581 case ZigTypeIdFloat: {
10582 if (float_is_nan(left))
10583 return false;
10584 if (right != nullptr && float_is_nan(right))
10585 return false;
10586
10587 const Cmp result = right ? float_cmp(left, right) : float_cmp_zero(left);
10588 return result == predicate;
10589 }
10590 case ZigTypeIdVector: {
10591 for (size_t i = 0; i < left->type->data.vector.len; i++) {
10592 ZigValue *scalar_val = &left->data.x_array.data.s_none.elements[i];
10593 const bool result = value_cmp_numeric_val(scalar_val, predicate, right, any);
10594
10595 if (any && result)
10596 return true; // This element satisfies the predicate
10597 else if (!any && !result)
10598 return false; // This element doesn't satisfy the predicate
10599 }
10600 return any ? false : true;
10601 }
10602 default:
10603 zig_unreachable();
10604 }
10605}
10606
10607static bool value_cmp_numeric_val_any(ZigValue *left, Cmp predicate, ZigValue *right) {
10608 return value_cmp_numeric_val(left, predicate, right, true);
10609}
10610
10611static bool value_cmp_numeric_val_all(ZigValue *left, Cmp predicate, ZigValue *right) {
10612 return value_cmp_numeric_val(left, predicate, right, false);
10613}
10614
10615static Stage1AirInst *ir_analyze_bin_op_math(IrAnalyze *ira, Stage1ZirInstBinOp *instruction) {
10616 Error err;
10617
10618 Stage1AirInst *op1 = instruction->op1->child;
10619 if (type_is_invalid(op1->value->type))
10620 return ira->codegen->invalid_inst_gen;
10621
10622 Stage1AirInst *op2 = instruction->op2->child;
10623 if (type_is_invalid(op2->value->type))
10624 return ira->codegen->invalid_inst_gen;
10625
10626 IrBinOp op_id = instruction->op_id;
10627
10628 // look for pointer math
10629 if (is_pointer_arithmetic_allowed(op1->value->type, op_id)) {
10630 Stage1AirInst *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize);
10631 if (type_is_invalid(casted_op2->value->type))
10632 return ira->codegen->invalid_inst_gen;
10633
10634 // If either operand is undef, result is undef.
10635 ZigValue *op1_val = nullptr;
10636 ZigValue *op2_val = nullptr;
10637 if (instr_is_comptime(op1)) {
10638 op1_val = ir_resolve_const(ira, op1, UndefOk);
10639 if (op1_val == nullptr)
10640 return ira->codegen->invalid_inst_gen;
10641 if (op1_val->special == ConstValSpecialUndef)
10642 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, op1->value->type);
10643 }
10644 if (instr_is_comptime(casted_op2)) {
10645 op2_val = ir_resolve_const(ira, casted_op2, UndefOk);
10646 if (op2_val == nullptr)
10647 return ira->codegen->invalid_inst_gen;
10648 if (op2_val->special == ConstValSpecialUndef)
10649 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, op1->value->type);
10650 }
10651
10652 ZigType *elem_type = op1->value->type->data.pointer.child_type;
10653 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
10654 return ira->codegen->invalid_inst_gen;
10655
10656 // NOTE: this variable is meaningful iff op2_val is not null!
10657 uint64_t byte_offset;
10658 if (op2_val != nullptr) {
10659 uint64_t elem_offset;
10660 if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
10661 return ira->codegen->invalid_inst_gen;
10662
10663 byte_offset = type_size(ira->codegen, elem_type) * elem_offset;
10664 }
10665
10666 // Fast path for cases where the RHS is zero
10667 if (op2_val != nullptr && byte_offset == 0) {
10668 return op1;
10669 }
10670
10671 ZigType *result_type = op1->value->type;
10672 // Calculate the new alignment of the pointer
10673 {
10674 uint32_t align_bytes;
10675 if ((err = resolve_ptr_align(ira, op1->value->type, &align_bytes)))
10676 return ira->codegen->invalid_inst_gen;
10677
10678 // If the addend is not a comptime-known value we can still count on
10679 // it being a multiple of the type size
10680 uint32_t addend = op2_val ? byte_offset : type_size(ira->codegen, elem_type);
10681
10682 // The resulting pointer is aligned to the lcd between the
10683 // offset (an arbitrary number) and the alignment factor (always
10684 // a power of two, non zero)
10685 uint32_t new_align = 1 << ctzll(addend | align_bytes);
10686 // Rough guard to prevent overflows
10687 assert(new_align);
10688 result_type = adjust_ptr_align(ira->codegen, result_type, new_align);
10689 }
10690
10691 if (op2_val != nullptr && op1_val != nullptr &&
10692 (op1->value->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
10693 op1->value->data.x_ptr.special == ConstPtrSpecialNull))
10694 {
10695 uint64_t start_addr = (op1_val->data.x_ptr.special == ConstPtrSpecialNull) ?
10696 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr;
10697 uint64_t new_addr;
10698 if (op_id == IrBinOpAdd) {
10699 new_addr = start_addr + byte_offset;
10700 } else if (op_id == IrBinOpSub) {
10701 new_addr = start_addr - byte_offset;
10702 } else {
10703 zig_unreachable();
10704 }
10705 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, result_type);
10706 result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
10707 result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar;
10708 result->value->data.x_ptr.data.hard_coded_addr.addr = new_addr;
10709 return result;
10710 }
10711
10712 return ir_build_bin_op_gen(ira, instruction->base.scope, instruction->base.source_node, result_type, op_id, op1, casted_op2, true);
10713 }
10714
10715 Stage1AirInst *instructions[] = {op1, op2};
10716 ZigType *resolved_type = ir_resolve_peer_types(ira, instruction->base.source_node, nullptr, instructions, 2);
10717 if (type_is_invalid(resolved_type))
10718 return ira->codegen->invalid_inst_gen;
10719
10720 ZigType *scalar_type = (resolved_type->id == ZigTypeIdVector) ?
10721 resolved_type->data.vector.elem_type : resolved_type;
10722
10723 bool is_int = scalar_type->id == ZigTypeIdInt || scalar_type->id == ZigTypeIdComptimeInt;
10724 bool is_float = scalar_type->id == ZigTypeIdFloat || scalar_type->id == ZigTypeIdComptimeFloat;
10725
10726 if (!is_int && !(is_float && ok_float_op(op_id))) {
10727 AstNode *source_node = instruction->base.source_node;
10728 ir_add_error_node(ira, source_node,
10729 buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
10730 buf_ptr(&op1->value->type->name),
10731 buf_ptr(&op2->value->type->name)));
10732 return ira->codegen->invalid_inst_gen;
10733 }
10734
10735 Stage1AirInst *casted_op1 = ir_implicit_cast(ira, op1, resolved_type);
10736 if (type_is_invalid(casted_op1->value->type))
10737 return ira->codegen->invalid_inst_gen;
10738
10739 Stage1AirInst *casted_op2 = ir_implicit_cast(ira, op2, resolved_type);
10740 if (type_is_invalid(casted_op2->value->type))
10741 return ira->codegen->invalid_inst_gen;
10742
10743 // Comptime integers have no fixed size, so wrapping or saturating operations should be mapped
10744 // to their non wrapping or saturating equivalents
10745 if (scalar_type->id == ZigTypeIdComptimeInt) {
10746 op_id = map_comptime_arithmetic_op(op_id);
10747 }
10748
10749 if (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2)) {
10750 ZigValue *op1_val = ir_resolve_const(ira, casted_op1, UndefBad);
10751 if (op1_val == nullptr)
10752 return ira->codegen->invalid_inst_gen;
10753
10754 ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
10755 if (op2_val == nullptr)
10756 return ira->codegen->invalid_inst_gen;
10757
10758 // Promote division with negative numbers to signed
10759 bool is_signed_div = value_cmp_numeric_val_any(op1_val, CmpLT, nullptr) ||
10760 value_cmp_numeric_val_any(op2_val, CmpLT, nullptr);
10761
10762 if (op_id == IrBinOpDivUnspecified && is_int) {
10763 // Default to truncating division and check if it's valid for the
10764 // given operands if signed
10765 op_id = IrBinOpDivTrunc;
10766
10767 if (is_signed_div) {
10768 bool ok = false;
10769
10770 if (value_cmp_numeric_val_any(op2_val, CmpEQ, nullptr)) {
10771 // the division by zero error will be caught later, but we don't have a
10772 // division function ambiguity problem.
10773 ok = true;
10774 } else {
10775 Stage1AirInst *trunc_val = ir_analyze_math_op(ira, instruction->base.scope, instruction->base.source_node, resolved_type,
10776 op1_val, IrBinOpDivTrunc, op2_val);
10777 if (type_is_invalid(trunc_val->value->type))
10778 return ira->codegen->invalid_inst_gen;
10779
10780 Stage1AirInst *floor_val = ir_analyze_math_op(ira, instruction->base.scope, instruction->base.source_node, resolved_type,
10781 op1_val, IrBinOpDivFloor, op2_val);
10782 if (type_is_invalid(floor_val->value->type))
10783 return ira->codegen->invalid_inst_gen;
10784
10785 Stage1AirInst *cmp_val = ir_analyze_bin_op_cmp_numeric(ira, instruction->base.scope, instruction->base.source_node,
10786 trunc_val, floor_val, IrBinOpCmpEq);
10787 if (type_is_invalid(cmp_val->value->type))
10788 return ira->codegen->invalid_inst_gen;
10789
10790 // We can "upgrade" the operator only if trunc(a/b) == floor(a/b)
10791 if (!ir_resolve_bool(ira, cmp_val, &ok))
10792 return ira->codegen->invalid_inst_gen;
10793 }
10794
10795 if (!ok) {
10796 ir_add_error_node(ira, instruction->base.source_node,
10797 buf_sprintf("division with '%s' and '%s': signed integers must use @divTrunc, @divFloor, or @divExact",
10798 buf_ptr(&op1->value->type->name),
10799 buf_ptr(&op2->value->type->name)));
10800 return ira->codegen->invalid_inst_gen;
10801 }
10802 }
10803 } else if (op_id == IrBinOpRemUnspecified) {
10804 op_id = IrBinOpRemRem;
10805
10806 if (is_signed_div) {
10807 bool ok = false;
10808
10809 if (value_cmp_numeric_val_any(op2_val, CmpEQ, nullptr)) {
10810 // the division by zero error will be caught later, but we don't have a
10811 // division function ambiguity problem.
10812 ok = true;
10813 } else {
10814 Stage1AirInst *rem_val = ir_analyze_math_op(ira, instruction->base.scope, instruction->base.source_node, resolved_type,
10815 op1_val, IrBinOpRemRem, op2_val);
10816 if (type_is_invalid(rem_val->value->type))
10817 return ira->codegen->invalid_inst_gen;
10818
10819 Stage1AirInst *mod_val = ir_analyze_math_op(ira, instruction->base.scope, instruction->base.source_node, resolved_type,
10820 op1_val, IrBinOpRemMod, op2_val);
10821 if (type_is_invalid(mod_val->value->type))
10822 return ira->codegen->invalid_inst_gen;
10823
10824 Stage1AirInst *cmp_val = ir_analyze_bin_op_cmp_numeric(ira, instruction->base.scope, instruction->base.source_node,
10825 rem_val, mod_val, IrBinOpCmpEq);
10826 if (type_is_invalid(cmp_val->value->type))
10827 return ira->codegen->invalid_inst_gen;
10828
10829 // We can "upgrade" the operator only if mod(a,b) == rem(a,b)
10830 if (!ir_resolve_bool(ira, cmp_val, &ok))
10831 return ira->codegen->invalid_inst_gen;
10832 }
10833
10834 if (!ok) {
10835 ir_add_error_node(ira, instruction->base.source_node,
10836 buf_sprintf("remainder division with '%s' and '%s': signed integers and floats must use @rem or @mod",
10837 buf_ptr(&op1->value->type->name),
10838 buf_ptr(&op2->value->type->name)));
10839 return ira->codegen->invalid_inst_gen;
10840 }
10841 }
10842 }
10843
10844 return ir_analyze_math_op(ira, instruction->base.scope, instruction->base.source_node, resolved_type, op1_val, op_id, op2_val);
10845 }
10846
10847 const bool is_signed_div =
10848 (scalar_type->id == ZigTypeIdInt && scalar_type->data.integral.is_signed) ||
10849 scalar_type->id == ZigTypeIdFloat;
10850
10851 // Warn the user to use the proper operators here
10852 if (op_id == IrBinOpDivUnspecified && is_int) {
10853 op_id = IrBinOpDivTrunc;
10854
10855 if (is_signed_div) {
10856 ir_add_error_node(ira, instruction->base.source_node,
10857 buf_sprintf("division with '%s' and '%s': signed integers must use @divTrunc, @divFloor, or @divExact",
10858 buf_ptr(&op1->value->type->name),
10859 buf_ptr(&op2->value->type->name)));
10860 return ira->codegen->invalid_inst_gen;
10861 }
10862 } else if (op_id == IrBinOpRemUnspecified) {
10863 op_id = IrBinOpRemRem;
10864
10865 if (is_signed_div) {
10866 ir_add_error_node(ira, instruction->base.source_node,
10867 buf_sprintf("remainder division with '%s' and '%s': signed integers and floats must use @rem or @mod",
10868 buf_ptr(&op1->value->type->name),
10869 buf_ptr(&op2->value->type->name)));
10870 return ira->codegen->invalid_inst_gen;
10871 }
10872 }
10873
10874 return ir_build_bin_op_gen(ira, instruction->base.scope, instruction->base.source_node, resolved_type,
10875 op_id, casted_op1, casted_op2, instruction->safety_check_on);
10876}
10877
10878static Stage1AirInst *ir_analyze_tuple_cat(IrAnalyze *ira, Scope *scope, AstNode *source_node,
10879 Stage1AirInst *op1, Stage1AirInst *op2)
10880{
10881 Error err;
10882 ZigType *op1_type = op1->value->type;
10883 ZigType *op2_type = op2->value->type;
10884
10885 uint32_t op1_field_count = op1_type->data.structure.src_field_count;
10886 uint32_t op2_field_count = op2_type->data.structure.src_field_count;
10887
10888 Buf *bare_name = buf_alloc();
10889 Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
10890 scope, source_node, bare_name, nullptr);
10891 ZigType *new_type = get_partial_container_type(ira->codegen, scope,
10892 ContainerKindStruct, source_node, buf_ptr(name), bare_name, ContainerLayoutAuto);
10893 new_type->data.structure.special = StructSpecialInferredTuple;
10894 new_type->data.structure.resolve_status = ResolveStatusBeingInferred;
10895 uint32_t new_field_count = op1_field_count + op2_field_count;
10896
10897 new_type->data.structure.src_field_count = new_field_count;
10898 new_type->data.structure.fields = realloc_type_struct_fields(new_type->data.structure.fields,
10899 0, new_field_count);
10900
10901 Stage1AirInst *new_struct_ptr = ir_resolve_result(ira, ira->suspend_source_instr, no_result_loc(),
10902 new_type, nullptr, false, true);
10903
10904 for (uint32_t i = 0; i < new_field_count; i += 1) {
10905 TypeStructField *src_field;
10906 if (i < op1_field_count) {
10907 src_field = op1_type->data.structure.fields[i];
10908 } else {
10909 src_field = op2_type->data.structure.fields[i - op1_field_count];
10910 }
10911 TypeStructField *new_field = new_type->data.structure.fields[i];
10912 new_field->name = buf_sprintf("%" PRIu32, i);
10913 new_field->type_entry = src_field->type_entry;
10914 new_field->type_val = src_field->type_val;
10915 new_field->src_index = i;
10916 new_field->decl_node = src_field->decl_node;
10917 new_field->init_val = src_field->init_val;
10918 new_field->is_comptime = src_field->is_comptime;
10919 }
10920 if ((err = type_resolve(ira->codegen, new_type, ResolveStatusZeroBitsKnown)))
10921 return ira->codegen->invalid_inst_gen;
10922
10923 ZigList<Stage1AirInst *> const_ptrs = {};
10924 for (uint32_t i = 0; i < new_field_count; i += 1) {
10925 TypeStructField *dst_field = new_type->data.structure.fields[i];
10926 Stage1AirInst *src_struct_op;
10927 TypeStructField *src_field;
10928 if (i < op1_field_count) {
10929 src_field = op1_type->data.structure.fields[i];
10930 src_struct_op = op1;
10931 } else {
10932 src_field = op2_type->data.structure.fields[i - op1_field_count];
10933 src_struct_op = op2;
10934 }
10935 Stage1AirInst *field_value = ir_analyze_struct_value_field_value(ira, scope, source_node,
10936 src_struct_op, src_field);
10937 if (type_is_invalid(field_value->value->type))
10938 return ira->codegen->invalid_inst_gen;
10939 Stage1AirInst *dest_ptr = ir_analyze_struct_field_ptr(ira, scope, source_node, dst_field,
10940 new_struct_ptr, new_type, true);
10941 if (type_is_invalid(dest_ptr->value->type))
10942 return ira->codegen->invalid_inst_gen;
10943 if (instr_is_comptime(field_value)) {
10944 const_ptrs.append(dest_ptr);
10945 }
10946 Stage1AirInst *store_ptr_inst = ir_analyze_store_ptr(ira, scope, source_node, dest_ptr, field_value,
10947 true);
10948 if (type_is_invalid(store_ptr_inst->value->type))
10949 return ira->codegen->invalid_inst_gen;
10950 }
10951 if (const_ptrs.length != new_field_count) {
10952 new_struct_ptr->value->special = ConstValSpecialRuntime;
10953 for (size_t i = 0; i < const_ptrs.length; i += 1) {
10954 Stage1AirInst *elem_result_loc = const_ptrs.at(i);
10955 assert(elem_result_loc->value->special == ConstValSpecialStatic);
10956 if (elem_result_loc->value->type->data.pointer.inferred_struct_field != nullptr) {
10957 // This field will be generated comptime; no need to do this.
10958 continue;
10959 }
10960 Stage1AirInst *deref = ir_get_deref(ira, elem_result_loc->scope,
10961 elem_result_loc->source_node, elem_result_loc, nullptr);
10962 if (!type_requires_comptime(ira->codegen, elem_result_loc->value->type->data.pointer.child_type)) {
10963 elem_result_loc->value->special = ConstValSpecialRuntime;
10964 }
10965 ir_analyze_store_ptr(ira, elem_result_loc->scope, elem_result_loc->source_node, elem_result_loc, deref, true);
10966 }
10967 }
10968
10969 const_ptrs.deinit();
10970
10971 return ir_get_deref(ira, scope, source_node, new_struct_ptr, nullptr);
10972}
10973
10974static Stage1AirInst *ir_analyze_array_cat(IrAnalyze *ira, Stage1ZirInstBinOp *instruction) {
10975 Stage1AirInst *op1 = instruction->op1->child;
10976 ZigType *op1_type = op1->value->type;
10977 if (type_is_invalid(op1_type))
10978 return ira->codegen->invalid_inst_gen;
10979
10980 Stage1AirInst *op2 = instruction->op2->child;
10981 ZigType *op2_type = op2->value->type;
10982 if (type_is_invalid(op2_type))
10983 return ira->codegen->invalid_inst_gen;
10984
10985 if (is_tuple(op1_type) && is_tuple(op2_type)) {
10986 return ir_analyze_tuple_cat(ira, instruction->base.scope, instruction->base.source_node, op1, op2);
10987 }
10988
10989 ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad);
10990 if (!op1_val)
10991 return ira->codegen->invalid_inst_gen;
10992
10993 ZigValue *op2_val = ir_resolve_const(ira, op2, UndefBad);
10994 if (!op2_val)
10995 return ira->codegen->invalid_inst_gen;
10996
10997 ZigValue *sentinel1 = nullptr;
10998 ZigValue *op1_array_val;
10999 size_t op1_array_index;
11000 size_t op1_array_end;
11001 ZigType *child_type;
11002 if (op1_type->id == ZigTypeIdArray) {
11003 child_type = op1_type->data.array.child_type;
11004 op1_array_val = op1_val;
11005 op1_array_index = 0;
11006 op1_array_end = op1_type->data.array.len;
11007 sentinel1 = op1_type->data.array.sentinel;
11008 } else if (op1_type->id == ZigTypeIdPointer &&
11009 op1_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
11010 op1_type->data.pointer.sentinel != nullptr &&
11011 op1_val->data.x_ptr.special == ConstPtrSpecialBaseArray)
11012 {
11013 child_type = op1_type->data.pointer.child_type;
11014 op1_array_val = op1_val->data.x_ptr.data.base_array.array_val;
11015 op1_array_index = op1_val->data.x_ptr.data.base_array.elem_index;
11016 op1_array_end = op1_array_val->type->data.array.len;
11017 sentinel1 = op1_type->data.pointer.sentinel;
11018 } else if (is_slice(op1_type)) {
11019 ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index]->type_entry;
11020 child_type = ptr_type->data.pointer.child_type;
11021 ZigValue *ptr_val = op1_val->data.x_struct.fields[slice_ptr_index];
11022 assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
11023 op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
11024 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
11025 ZigValue *len_val = op1_val->data.x_struct.fields[slice_len_index];
11026 op1_array_end = op1_array_index + bigint_as_usize(&len_val->data.x_bigint);
11027 sentinel1 = ptr_type->data.pointer.sentinel;
11028 } else if (op1_type->id == ZigTypeIdPointer &&
11029 op1_type->data.pointer.ptr_len == PtrLenSingle &&
11030 op1_type->data.pointer.child_type->id == ZigTypeIdArray)
11031 {
11032 ZigType *array_type = op1_type->data.pointer.child_type;
11033 child_type = array_type->data.array.child_type;
11034 op1_array_val = const_ptr_pointee(ira, ira->codegen, op1_val, op1->source_node);
11035 if (op1_array_val == nullptr)
11036 return ira->codegen->invalid_inst_gen;
11037 op1_array_index = 0;
11038 op1_array_end = array_type->data.array.len;
11039 sentinel1 = array_type->data.array.sentinel;
11040 } else {
11041 ir_add_error(ira, op1, buf_sprintf("expected array, found '%s'", buf_ptr(&op1->value->type->name)));
11042 return ira->codegen->invalid_inst_gen;
11043 }
11044
11045 ZigValue *sentinel2 = nullptr;
11046 ZigValue *op2_array_val;
11047 size_t op2_array_index;
11048 size_t op2_array_end;
11049 bool op2_type_valid;
11050 if (op2_type->id == ZigTypeIdArray) {
11051 op2_type_valid = op2_type->data.array.child_type == child_type;
11052 op2_array_val = op2_val;
11053 op2_array_index = 0;
11054 op2_array_end = op2_array_val->type->data.array.len;
11055 sentinel2 = op2_type->data.array.sentinel;
11056 } else if (op2_type->id == ZigTypeIdPointer &&
11057 op2_type->data.pointer.sentinel != nullptr &&
11058 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray)
11059 {
11060 op2_type_valid = op2_type->data.pointer.child_type == child_type;
11061 op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;
11062 op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;
11063 op2_array_end = op2_array_val->type->data.array.len;
11064
11065 sentinel2 = op2_type->data.pointer.sentinel;
11066 } else if (is_slice(op2_type)) {
11067 ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index]->type_entry;
11068 op2_type_valid = ptr_type->data.pointer.child_type == child_type;
11069 ZigValue *ptr_val = op2_val->data.x_struct.fields[slice_ptr_index];
11070 assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
11071 op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
11072 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
11073 ZigValue *len_val = op2_val->data.x_struct.fields[slice_len_index];
11074 op2_array_end = op2_array_index + bigint_as_usize(&len_val->data.x_bigint);
11075
11076 sentinel2 = ptr_type->data.pointer.sentinel;
11077 } else if (op2_type->id == ZigTypeIdPointer && op2_type->data.pointer.ptr_len == PtrLenSingle &&
11078 op2_type->data.pointer.child_type->id == ZigTypeIdArray)
11079 {
11080 ZigType *array_type = op2_type->data.pointer.child_type;
11081 op2_type_valid = array_type->data.array.child_type == child_type;
11082 op2_array_val = const_ptr_pointee(ira, ira->codegen, op2_val, op2->source_node);
11083 if (op2_array_val == nullptr)
11084 return ira->codegen->invalid_inst_gen;
11085 op2_array_index = 0;
11086 op2_array_end = array_type->data.array.len;
11087
11088 sentinel2 = array_type->data.array.sentinel;
11089 } else {
11090 ir_add_error(ira, op2,
11091 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value->type->name)));
11092 return ira->codegen->invalid_inst_gen;
11093 }
11094 if (!op2_type_valid) {
11095 ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
11096 buf_ptr(&child_type->name),
11097 buf_ptr(&op2->value->type->name)));
11098 return ira->codegen->invalid_inst_gen;
11099 }
11100
11101 ZigValue *sentinel;
11102 if (sentinel1 != nullptr && sentinel2 != nullptr) {
11103 // When there is a sentinel mismatch, no sentinel on the result. The type system
11104 // will catch this if it is a problem.
11105 sentinel = const_values_equal(ira->codegen, sentinel1, sentinel2) ? sentinel1 : nullptr;
11106 } else if (sentinel1 != nullptr) {
11107 sentinel = sentinel1;
11108 } else if (sentinel2 != nullptr) {
11109 sentinel = sentinel2;
11110 } else {
11111 sentinel = nullptr;
11112 }
11113
11114 // The type of result is populated in the following if blocks
11115 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, nullptr);
11116 ZigValue *out_val = result->value;
11117
11118 ZigValue *out_array_val;
11119 size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index);
11120 if (op1_type->id == ZigTypeIdPointer || op2_type->id == ZigTypeIdPointer) {
11121 out_array_val = ira->codegen->pass1_arena->create<ZigValue>();
11122 out_array_val->special = ConstValSpecialStatic;
11123 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, sentinel);
11124
11125 out_val->data.x_ptr.special = ConstPtrSpecialRef;
11126 out_val->data.x_ptr.data.ref.pointee = out_array_val;
11127 out_val->type = get_pointer_to_type(ira->codegen, out_array_val->type, true);
11128 } else if (is_slice(op1_type) || is_slice(op2_type)) {
11129 ZigType *ptr_type = get_pointer_to_type_extra2(ira->codegen, child_type,
11130 true, false, PtrLenUnknown, 0, 0, 0, false,
11131 VECTOR_INDEX_NONE, nullptr, sentinel);
11132 result->value->type = get_slice_type(ira->codegen, ptr_type);
11133 out_array_val = ira->codegen->pass1_arena->create<ZigValue>();
11134 out_array_val->special = ConstValSpecialStatic;
11135 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, sentinel);
11136
11137 out_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2);
11138
11139 out_val->data.x_struct.fields[slice_ptr_index]->type = ptr_type;
11140 out_val->data.x_struct.fields[slice_ptr_index]->special = ConstValSpecialStatic;
11141 out_val->data.x_struct.fields[slice_ptr_index]->data.x_ptr.special = ConstPtrSpecialBaseArray;
11142 out_val->data.x_struct.fields[slice_ptr_index]->data.x_ptr.data.base_array.array_val = out_array_val;
11143 out_val->data.x_struct.fields[slice_ptr_index]->data.x_ptr.data.base_array.elem_index = 0;
11144
11145 out_val->data.x_struct.fields[slice_len_index]->type = ira->codegen->builtin_types.entry_usize;
11146 out_val->data.x_struct.fields[slice_len_index]->special = ConstValSpecialStatic;
11147 bigint_init_unsigned(&out_val->data.x_struct.fields[slice_len_index]->data.x_bigint, new_len);
11148 } else if (op1_type->id == ZigTypeIdArray || op2_type->id == ZigTypeIdArray) {
11149 result->value->type = get_array_type(ira->codegen, child_type, new_len, sentinel);
11150 out_array_val = out_val;
11151 } else {
11152 result->value->type = get_pointer_to_type_extra2(ira->codegen, child_type, true, false, PtrLenUnknown,
11153 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, sentinel);
11154 out_array_val = ira->codegen->pass1_arena->create<ZigValue>();
11155 out_array_val->special = ConstValSpecialStatic;
11156 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, sentinel);
11157 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
11158 out_val->data.x_ptr.data.base_array.array_val = out_array_val;
11159 out_val->data.x_ptr.data.base_array.elem_index = 0;
11160 }
11161
11162 if (op1_array_val->data.x_array.special == ConstArraySpecialUndef &&
11163 op2_array_val->data.x_array.special == ConstArraySpecialUndef)
11164 {
11165 out_array_val->data.x_array.special = ConstArraySpecialUndef;
11166 return result;
11167 }
11168
11169 uint64_t full_len = new_len + ((sentinel != nullptr) ? 1 : 0);
11170 out_array_val->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(full_len);
11171 // TODO handle the buf case here for an optimization
11172 expand_undef_array(ira->codegen, op1_array_val);
11173 expand_undef_array(ira->codegen, op2_array_val);
11174
11175 size_t next_index = 0;
11176 for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {
11177 ZigValue *elem_dest_val = &out_array_val->data.x_array.data.s_none.elements[next_index];
11178 copy_const_val(ira->codegen, elem_dest_val, &op1_array_val->data.x_array.data.s_none.elements[i]);
11179 elem_dest_val->parent.id = ConstParentIdArray;
11180 elem_dest_val->parent.data.p_array.array_val = out_array_val;
11181 elem_dest_val->parent.data.p_array.elem_index = next_index;
11182 }
11183 for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) {
11184 ZigValue *elem_dest_val = &out_array_val->data.x_array.data.s_none.elements[next_index];
11185 copy_const_val(ira->codegen, elem_dest_val, &op2_array_val->data.x_array.data.s_none.elements[i]);
11186 elem_dest_val->parent.id = ConstParentIdArray;
11187 elem_dest_val->parent.data.p_array.array_val = out_array_val;
11188 elem_dest_val->parent.data.p_array.elem_index = next_index;
11189 }
11190 if (next_index < full_len) {
11191 ZigValue *elem_dest_val = &out_array_val->data.x_array.data.s_none.elements[next_index];
11192 copy_const_val(ira->codegen, elem_dest_val, sentinel);
11193 elem_dest_val->parent.id = ConstParentIdArray;
11194 elem_dest_val->parent.data.p_array.array_val = out_array_val;
11195 elem_dest_val->parent.data.p_array.elem_index = next_index;
11196 next_index += 1;
11197 }
11198 assert(next_index == full_len);
11199
11200 return result;
11201}
11202
11203static Stage1AirInst *ir_analyze_tuple_mult(IrAnalyze *ira, Scope *scope, AstNode *source_node,
11204 Stage1AirInst *op1, Stage1AirInst *op2)
11205{
11206 Error err;
11207 ZigType *op1_type = op1->value->type;
11208 uint64_t op1_field_count = op1_type->data.structure.src_field_count;
11209
11210 uint64_t mult_amt;
11211 if (!ir_resolve_usize(ira, op2, &mult_amt))
11212 return ira->codegen->invalid_inst_gen;
11213
11214 uint64_t new_field_count;
11215 if (mul_u64_overflow(op1_field_count, mult_amt, &new_field_count)) {
11216 ir_add_error_node(ira, source_node, buf_sprintf("operation results in overflow"));
11217 return ira->codegen->invalid_inst_gen;
11218 }
11219
11220 Buf *bare_name = buf_alloc();
11221 Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
11222 scope, source_node, bare_name, nullptr);
11223 ZigType *new_type = get_partial_container_type(ira->codegen, scope,
11224 ContainerKindStruct, source_node, buf_ptr(name), bare_name, ContainerLayoutAuto);
11225 new_type->data.structure.special = StructSpecialInferredTuple;
11226 new_type->data.structure.resolve_status = ResolveStatusBeingInferred;
11227 new_type->data.structure.src_field_count = new_field_count;
11228 new_type->data.structure.fields = realloc_type_struct_fields(
11229 new_type->data.structure.fields, 0, new_field_count);
11230
11231 Stage1AirInst *new_struct_ptr = ir_resolve_result(ira, ira->suspend_source_instr, no_result_loc(),
11232 new_type, nullptr, false, true);
11233
11234 for (uint64_t i = 0; i < new_field_count; i += 1) {
11235 TypeStructField *src_field = op1_type->data.structure.fields[i % op1_field_count];
11236 TypeStructField *new_field = new_type->data.structure.fields[i];
11237
11238 new_field->name = buf_sprintf("%" ZIG_PRI_u64, i);
11239 new_field->type_entry = src_field->type_entry;
11240 new_field->type_val = src_field->type_val;
11241 new_field->src_index = i;
11242 new_field->decl_node = src_field->decl_node;
11243 new_field->init_val = src_field->init_val;
11244 new_field->is_comptime = src_field->is_comptime;
11245 }
11246
11247 if ((err = type_resolve(ira->codegen, new_type, ResolveStatusZeroBitsKnown)))
11248 return ira->codegen->invalid_inst_gen;
11249
11250 ZigList<Stage1AirInst *> const_ptrs = {};
11251 for (uint64_t i = 0; i < new_field_count; i += 1) {
11252 TypeStructField *src_field = op1_type->data.structure.fields[i % op1_field_count];
11253 TypeStructField *dst_field = new_type->data.structure.fields[i];
11254
11255 Stage1AirInst *field_value = ir_analyze_struct_value_field_value(
11256 ira, scope, source_node, op1, src_field);
11257 if (type_is_invalid(field_value->value->type))
11258 return ira->codegen->invalid_inst_gen;
11259
11260 Stage1AirInst *dest_ptr = ir_analyze_struct_field_ptr(
11261 ira, scope, source_node, dst_field, new_struct_ptr, new_type, true);
11262 if (type_is_invalid(dest_ptr->value->type))
11263 return ira->codegen->invalid_inst_gen;
11264
11265 if (instr_is_comptime(field_value)) {
11266 const_ptrs.append(dest_ptr);
11267 }
11268
11269 Stage1AirInst *store_ptr_inst = ir_analyze_store_ptr(
11270 ira, scope, source_node, dest_ptr, field_value, true);
11271 if (type_is_invalid(store_ptr_inst->value->type))
11272 return ira->codegen->invalid_inst_gen;
11273 }
11274
11275 if (const_ptrs.length != new_field_count) {
11276 new_struct_ptr->value->special = ConstValSpecialRuntime;
11277 for (size_t i = 0; i < const_ptrs.length; i += 1) {
11278 Stage1AirInst *elem_result_loc = const_ptrs.at(i);
11279 assert(elem_result_loc->value->special == ConstValSpecialStatic);
11280 if (elem_result_loc->value->type->data.pointer.inferred_struct_field != nullptr) {
11281 // This field will be generated comptime; no need to do this.
11282 continue;
11283 }
11284 Stage1AirInst *deref = ir_get_deref(ira, elem_result_loc->scope,
11285 elem_result_loc->source_node, elem_result_loc, nullptr);
11286 if (!type_requires_comptime(ira->codegen, elem_result_loc->value->type->data.pointer.child_type)) {
11287 elem_result_loc->value->special = ConstValSpecialRuntime;
11288 }
11289 Stage1AirInst *store_ptr_inst = ir_analyze_store_ptr(ira, elem_result_loc->scope,
11290 elem_result_loc->source_node, elem_result_loc, deref, true);
11291 if (type_is_invalid(store_ptr_inst->value->type))
11292 return ira->codegen->invalid_inst_gen;
11293 }
11294 }
11295
11296 const_ptrs.deinit();
11297
11298 return ir_get_deref(ira, scope, source_node, new_struct_ptr, nullptr);
11299}
11300
11301static Stage1AirInst *ir_analyze_array_mult(IrAnalyze *ira, Stage1ZirInstBinOp *instruction) {
11302 Stage1AirInst *op1 = instruction->op1->child;
11303 if (type_is_invalid(op1->value->type))
11304 return ira->codegen->invalid_inst_gen;
11305
11306 Stage1AirInst *op2 = instruction->op2->child;
11307 if (type_is_invalid(op2->value->type))
11308 return ira->codegen->invalid_inst_gen;
11309
11310 bool want_ptr_to_array = false;
11311 ZigType *array_type;
11312 ZigValue *array_val;
11313 if (op1->value->type->id == ZigTypeIdArray) {
11314 array_type = op1->value->type;
11315 array_val = ir_resolve_const(ira, op1, UndefOk);
11316 if (array_val == nullptr)
11317 return ira->codegen->invalid_inst_gen;
11318 } else if (op1->value->type->id == ZigTypeIdPointer &&
11319 op1->value->type->data.pointer.ptr_len == PtrLenSingle &&
11320 op1->value->type->data.pointer.child_type->id == ZigTypeIdArray)
11321 {
11322 array_type = op1->value->type->data.pointer.child_type;
11323 Stage1AirInst *array_inst = ir_get_deref(ira, op1->scope, op1->source_node, op1, nullptr);
11324 if (type_is_invalid(array_inst->value->type))
11325 return ira->codegen->invalid_inst_gen;
11326 array_val = ir_resolve_const(ira, array_inst, UndefOk);
11327 if (array_val == nullptr)
11328 return ira->codegen->invalid_inst_gen;
11329 want_ptr_to_array = true;
11330 } else if (is_tuple(op1->value->type)) {
11331 return ir_analyze_tuple_mult(ira, instruction->base.scope, instruction->base.source_node, op1, op2);
11332 } else {
11333 ir_add_error(ira, op1, buf_sprintf("expected array type, found '%s'", buf_ptr(&op1->value->type->name)));
11334 return ira->codegen->invalid_inst_gen;
11335 }
11336
11337 uint64_t mult_amt;
11338 if (!ir_resolve_usize(ira, op2, &mult_amt))
11339 return ira->codegen->invalid_inst_gen;
11340
11341 uint64_t old_array_len = array_type->data.array.len;
11342 uint64_t new_array_len;
11343
11344 if (mul_u64_overflow(old_array_len, mult_amt, &new_array_len)) {
11345 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("operation results in overflow"));
11346 return ira->codegen->invalid_inst_gen;
11347 }
11348
11349 ZigType *child_type = array_type->data.array.child_type;
11350 ZigType *result_array_type = get_array_type(ira->codegen, child_type, new_array_len,
11351 array_type->data.array.sentinel);
11352
11353 Stage1AirInst *array_result;
11354 if (array_val->special == ConstValSpecialUndef || array_val->data.x_array.special == ConstArraySpecialUndef) {
11355 array_result = ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, result_array_type);
11356 } else {
11357 array_result = ir_const(ira, instruction->base.scope, instruction->base.source_node, result_array_type);
11358 ZigValue *out_val = array_result->value;
11359
11360 switch (type_has_one_possible_value(ira->codegen, result_array_type)) {
11361 case OnePossibleValueInvalid:
11362 return ira->codegen->invalid_inst_gen;
11363 case OnePossibleValueYes:
11364 goto skip_computation;
11365 case OnePossibleValueNo:
11366 break;
11367 }
11368
11369 // TODO optimize the buf case
11370 expand_undef_array(ira->codegen, array_val);
11371 size_t extra_null_term = (array_type->data.array.sentinel != nullptr) ? 1 : 0;
11372 out_val->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(new_array_len + extra_null_term);
11373
11374 uint64_t i = 0;
11375 for (uint64_t x = 0; x < mult_amt; x += 1) {
11376 for (uint64_t y = 0; y < old_array_len; y += 1) {
11377 ZigValue *elem_dest_val = &out_val->data.x_array.data.s_none.elements[i];
11378 copy_const_val(ira->codegen, elem_dest_val, &array_val->data.x_array.data.s_none.elements[y]);
11379 elem_dest_val->parent.id = ConstParentIdArray;
11380 elem_dest_val->parent.data.p_array.array_val = out_val;
11381 elem_dest_val->parent.data.p_array.elem_index = i;
11382 i += 1;
11383 }
11384 }
11385 assert(i == new_array_len);
11386
11387 if (array_type->data.array.sentinel != nullptr) {
11388 ZigValue *elem_dest_val = &out_val->data.x_array.data.s_none.elements[i];
11389 copy_const_val(ira->codegen, elem_dest_val, array_type->data.array.sentinel);
11390 elem_dest_val->parent.id = ConstParentIdArray;
11391 elem_dest_val->parent.data.p_array.array_val = out_val;
11392 elem_dest_val->parent.data.p_array.elem_index = i;
11393 i += 1;
11394 }
11395 }
11396skip_computation:
11397 if (want_ptr_to_array) {
11398 return ir_get_ref(ira, instruction->base.scope, instruction->base.source_node, array_result, true, false);
11399 } else {
11400 return array_result;
11401 }
11402}
11403
11404static Stage1AirInst *ir_analyze_instruction_merge_err_sets(IrAnalyze *ira,
11405 Stage1ZirInstMergeErrSets *instruction)
11406{
11407 ZigType *op1_type = ir_resolve_error_set_type(ira, instruction->base.source_node, instruction->op1->child);
11408 if (type_is_invalid(op1_type))
11409 return ira->codegen->invalid_inst_gen;
11410
11411 ZigType *op2_type = ir_resolve_error_set_type(ira, instruction->base.source_node, instruction->op2->child);
11412 if (type_is_invalid(op2_type))
11413 return ira->codegen->invalid_inst_gen;
11414
11415 if (!resolve_inferred_error_set(ira->codegen, op1_type, instruction->op1->child->source_node)) {
11416 return ira->codegen->invalid_inst_gen;
11417 }
11418
11419 if (!resolve_inferred_error_set(ira->codegen, op2_type, instruction->op2->child->source_node)) {
11420 return ira->codegen->invalid_inst_gen;
11421 }
11422
11423 if (type_is_global_error_set(op1_type) ||
11424 type_is_global_error_set(op2_type))
11425 {
11426 return ir_const_type(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_global_error_set);
11427 }
11428
11429 size_t errors_count = ira->codegen->errors_by_index.length;
11430 ErrorTableEntry **errors = heap::c_allocator.allocate<ErrorTableEntry *>(errors_count);
11431 for (uint32_t i = 0, count = op1_type->data.error_set.err_count; i < count; i += 1) {
11432 ErrorTableEntry *error_entry = op1_type->data.error_set.errors[i];
11433 assert(errors[error_entry->value] == nullptr);
11434 errors[error_entry->value] = error_entry;
11435 }
11436 ZigType *result_type = get_error_set_union(ira->codegen, errors, op1_type, op2_type, instruction->type_name);
11437 heap::c_allocator.deallocate(errors, errors_count);
11438
11439 return ir_const_type(ira, instruction->base.scope, instruction->base.source_node, result_type);
11440}
11441
11442
11443static Stage1AirInst *ir_analyze_instruction_bin_op(IrAnalyze *ira, Stage1ZirInstBinOp *bin_op_instruction) {
11444 IrBinOp op_id = bin_op_instruction->op_id;
11445 switch (op_id) {
11446 case IrBinOpInvalid:
11447 zig_unreachable();
11448 case IrBinOpBoolOr:
11449 case IrBinOpBoolAnd:
11450 return ir_analyze_bin_op_bool(ira, bin_op_instruction);
11451 case IrBinOpCmpEq:
11452 case IrBinOpCmpNotEq:
11453 case IrBinOpCmpLessThan:
11454 case IrBinOpCmpGreaterThan:
11455 case IrBinOpCmpLessOrEq:
11456 case IrBinOpCmpGreaterOrEq:
11457 return ir_analyze_bin_op_cmp(ira, bin_op_instruction);
11458 case IrBinOpBitShiftLeftLossy:
11459 case IrBinOpBitShiftLeftExact:
11460 case IrBinOpBitShiftRightLossy:
11461 case IrBinOpBitShiftRightExact:
11462 case IrBinOpShlSat:
11463 return ir_analyze_bit_shift(ira, bin_op_instruction);
11464 case IrBinOpBinOr:
11465 case IrBinOpBinXor:
11466 case IrBinOpBinAnd:
11467 case IrBinOpAdd:
11468 case IrBinOpAddWrap:
11469 case IrBinOpSub:
11470 case IrBinOpSubWrap:
11471 case IrBinOpMult:
11472 case IrBinOpMultWrap:
11473 case IrBinOpDivUnspecified:
11474 case IrBinOpDivTrunc:
11475 case IrBinOpDivFloor:
11476 case IrBinOpDivExact:
11477 case IrBinOpRemUnspecified:
11478 case IrBinOpRemRem:
11479 case IrBinOpRemMod:
11480 case IrBinOpMax:
11481 case IrBinOpMin:
11482 case IrBinOpAddSat:
11483 case IrBinOpSubSat:
11484 case IrBinOpMultSat:
11485 return ir_analyze_bin_op_math(ira, bin_op_instruction);
11486 case IrBinOpArrayCat:
11487 return ir_analyze_array_cat(ira, bin_op_instruction);
11488 case IrBinOpArrayMult:
11489 return ir_analyze_array_mult(ira, bin_op_instruction);
11490 }
11491 zig_unreachable();
11492}
11493
11494static Stage1AirInst *ir_analyze_instruction_decl_var(IrAnalyze *ira, Stage1ZirInstDeclVar *decl_var_instruction) {
11495 Error err;
11496 ZigVar *var = decl_var_instruction->var;
11497
11498 ZigType *explicit_type = nullptr;
11499 Stage1AirInst *var_type = nullptr;
11500 if (decl_var_instruction->var_type != nullptr) {
11501 var_type = decl_var_instruction->var_type->child;
11502 ZigType *proposed_type = ir_resolve_type(ira, var_type);
11503 explicit_type = validate_var_type(ira->codegen, &var->decl_node->data.variable_declaration, proposed_type);
11504 if (type_is_invalid(explicit_type)) {
11505 var->var_type = ira->codegen->builtin_types.entry_invalid;
11506 return ira->codegen->invalid_inst_gen;
11507 }
11508 }
11509
11510 AstNode *source_node = decl_var_instruction->base.source_node;
11511
11512 bool is_comptime_var = ir_get_var_is_comptime(var);
11513
11514 bool var_class_requires_const = false;
11515
11516 Stage1AirInst *var_ptr = decl_var_instruction->ptr->child;
11517 // if this is null, a compiler error happened and did not initialize the variable.
11518 // if there are no compile errors there may be a missing ir_expr_wrap in pass1 IR generation.
11519 if (var_ptr == nullptr || type_is_invalid(var_ptr->value->type)) {
11520 src_assert(var_ptr != nullptr || ira->codegen->errors.length != 0,
11521 decl_var_instruction->base.source_node);
11522 var->var_type = ira->codegen->builtin_types.entry_invalid;
11523 return ira->codegen->invalid_inst_gen;
11524 }
11525
11526 // The ir_build_var_decl_src call is supposed to pass a pointer to the allocation, not an initialization value.
11527 src_assert(var_ptr->value->type->id == ZigTypeIdPointer, decl_var_instruction->base.source_node);
11528
11529 ZigType *result_type = var_ptr->value->type->data.pointer.child_type;
11530 if (type_is_invalid(result_type)) {
11531 result_type = ira->codegen->builtin_types.entry_invalid;
11532 } else if (result_type->id == ZigTypeIdUnreachable || result_type->id == ZigTypeIdOpaque) {
11533 zig_unreachable();
11534 }
11535
11536 ZigValue *init_val = nullptr;
11537 if (instr_is_comptime(var_ptr) && var_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
11538 ZigValue *ptr_val = ir_resolve_const(ira, var_ptr, UndefBad);
11539 if (ptr_val == nullptr)
11540 return ira->codegen->invalid_inst_gen;
11541
11542 init_val = const_ptr_pointee(ira, ira->codegen, ptr_val, decl_var_instruction->base.source_node);
11543 if (init_val == nullptr)
11544 return ira->codegen->invalid_inst_gen;
11545
11546 if (is_comptime_var) {
11547 if (var->gen_is_const) {
11548 var->const_value = init_val;
11549 } else {
11550 var->const_value = ira->codegen->pass1_arena->create<ZigValue>();
11551 copy_const_val(ira->codegen, var->const_value, init_val);
11552 }
11553 }
11554 }
11555
11556 switch (type_requires_comptime(ira->codegen, result_type)) {
11557 case ReqCompTimeInvalid:
11558 result_type = ira->codegen->builtin_types.entry_invalid;
11559 break;
11560 case ReqCompTimeYes:
11561 var_class_requires_const = true;
11562 if (!var->gen_is_const && !is_comptime_var) {
11563 ErrorMsg *msg = ir_add_error_node(ira, source_node,
11564 buf_sprintf("variable of type '%s' must be const or comptime",
11565 buf_ptr(&result_type->name)));
11566 if(result_type->id == ZigTypeIdComptimeInt || result_type -> id == ZigTypeIdComptimeFloat) {
11567 add_error_note(ira->codegen, msg, source_node, buf_sprintf("to modify this variable at runtime, it must be given an explicit fixed-size number type"));
11568 }
11569 result_type = ira->codegen->builtin_types.entry_invalid;
11570 }
11571 break;
11572 case ReqCompTimeNo:
11573 if (init_val != nullptr && value_is_comptime(init_val)) {
11574 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec,
11575 decl_var_instruction->base.source_node, init_val, UndefOk)))
11576 {
11577 result_type = ira->codegen->builtin_types.entry_invalid;
11578 } else if (init_val->type->id == ZigTypeIdFn &&
11579 init_val->special != ConstValSpecialUndef &&
11580 init_val->data.x_ptr.special == ConstPtrSpecialFunction &&
11581 init_val->data.x_ptr.data.fn.fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionInline)
11582 {
11583 var_class_requires_const = true;
11584 if (!var->src_is_const && !is_comptime_var) {
11585 ErrorMsg *msg = ir_add_error_node(ira, source_node,
11586 buf_sprintf("functions marked inline must be stored in const or comptime var"));
11587 AstNode *proto_node = init_val->data.x_ptr.data.fn.fn_entry->proto_node;
11588 add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here"));
11589 result_type = ira->codegen->builtin_types.entry_invalid;
11590 }
11591 }
11592 }
11593 break;
11594 }
11595
11596 while (var->next_var != nullptr) {
11597 var = var->next_var;
11598 }
11599
11600 // This must be done after possibly creating a new variable above
11601 var->ref_count = 0;
11602
11603 var->ptr_instruction = var_ptr;
11604 var->var_type = result_type;
11605 assert(var->var_type);
11606
11607 if (type_is_invalid(result_type)) {
11608 return ir_const_void(ira, decl_var_instruction->base.scope, decl_var_instruction->base.source_node);
11609 }
11610
11611 if (decl_var_instruction->align_value == nullptr) {
11612 if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) {
11613 var->var_type = ira->codegen->builtin_types.entry_invalid;
11614 return ir_const_void(ira, decl_var_instruction->base.scope, decl_var_instruction->base.source_node);
11615 }
11616 var->align_bytes = get_ptr_align(ira->codegen, var_ptr->value->type);
11617 } else {
11618 if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, nullptr, &var->align_bytes)) {
11619 var->var_type = ira->codegen->builtin_types.entry_invalid;
11620 }
11621 }
11622
11623 if (init_val != nullptr && value_is_comptime(init_val)) {
11624 // Resolve ConstPtrMutInfer
11625 if (var->gen_is_const) {
11626 var_ptr->value->data.x_ptr.mut = ConstPtrMutComptimeConst;
11627 } else if (is_comptime_var) {
11628 var_ptr->value->data.x_ptr.mut = ConstPtrMutComptimeVar;
11629 } else {
11630 // we need a runtime ptr but we have a comptime val.
11631 // since it's a comptime val there are no instructions for it.
11632 // we memcpy the init value here
11633 Stage1AirInst *deref = ir_get_deref(ira, var_ptr->scope, var_ptr->source_node, var_ptr, nullptr);
11634 if (type_is_invalid(deref->value->type)) {
11635 var->var_type = ira->codegen->builtin_types.entry_invalid;
11636 return ira->codegen->invalid_inst_gen;
11637 }
11638 // If this assertion trips, something is wrong with the IR instructions, because
11639 // we expected the above deref to return a constant value, but it created a runtime
11640 // instruction.
11641 assert(deref->value->special != ConstValSpecialRuntime);
11642 var_ptr->value->special = ConstValSpecialRuntime;
11643 ir_analyze_store_ptr(ira, var_ptr->scope, var_ptr->source_node, var_ptr, deref, false);
11644 }
11645 if (instr_is_comptime(var_ptr) && (is_comptime_var || (var_class_requires_const && var->gen_is_const))) {
11646 return ir_const_void(ira, decl_var_instruction->base.scope, decl_var_instruction->base.source_node);
11647 }
11648 } else if (is_comptime_var) {
11649 ir_add_error_node(ira, decl_var_instruction->base.source_node,
11650 buf_sprintf("cannot store runtime value in compile time variable"));
11651 var->var_type = ira->codegen->builtin_types.entry_invalid;
11652 return ira->codegen->invalid_inst_gen;
11653 }
11654
11655 ZigFn *fn_entry = ira->fn;
11656 if (fn_entry)
11657 fn_entry->variable_list.append(var);
11658
11659 return ir_build_var_decl_gen(ira, decl_var_instruction->base.scope, decl_var_instruction->base.source_node, var, var_ptr);
11660}
11661
11662static Stage1AirInst *ir_analyze_instruction_export(IrAnalyze *ira, Stage1ZirInstExport *instruction) {
11663 Stage1AirInst *target = instruction->target->child;
11664 if (type_is_invalid(target->value->type))
11665 return ira->codegen->invalid_inst_gen;
11666
11667 Stage1AirInst *options = instruction->options->child;
11668 if (type_is_invalid(options->value->type))
11669 return ira->codegen->invalid_inst_gen;
11670
11671 ZigType *options_type = options->value->type;
11672 assert(options_type->id == ZigTypeIdStruct);
11673
11674 TypeStructField *name_field = find_struct_type_field(options_type, buf_create_from_str("name"));
11675 src_assert(name_field != nullptr, instruction->base.source_node);
11676 Stage1AirInst *name_inst = ir_analyze_struct_value_field_value(ira, instruction->base.scope, instruction->base.source_node, options, name_field);
11677 if (type_is_invalid(name_inst->value->type))
11678 return ira->codegen->invalid_inst_gen;
11679
11680 TypeStructField *linkage_field = find_struct_type_field(options_type, buf_create_from_str("linkage"));
11681 src_assert(linkage_field != nullptr, instruction->base.source_node);
11682 Stage1AirInst *linkage_inst = ir_analyze_struct_value_field_value(ira, instruction->base.scope, instruction->base.source_node, options, linkage_field);
11683 if (type_is_invalid(linkage_inst->value->type))
11684 return ira->codegen->invalid_inst_gen;
11685
11686 TypeStructField *section_field = find_struct_type_field(options_type, buf_create_from_str("section"));
11687 src_assert(section_field != nullptr, instruction->base.source_node);
11688 Stage1AirInst *section_inst = ir_analyze_struct_value_field_value(ira, instruction->base.scope, instruction->base.source_node, options, section_field);
11689 if (type_is_invalid(section_inst->value->type))
11690 return ira->codegen->invalid_inst_gen;
11691
11692 // The `section` field is optional, we have to unwrap it first
11693 Stage1AirInst *non_null_check = ir_analyze_test_non_null(ira, instruction->base.scope, instruction->base.source_node, section_inst);
11694 bool is_non_null;
11695 if (!ir_resolve_bool(ira, non_null_check, &is_non_null))
11696 return ira->codegen->invalid_inst_gen;
11697
11698 Stage1AirInst *section_str_inst = nullptr;
11699 if (is_non_null) {
11700 section_str_inst = ir_analyze_optional_value_payload_value(ira, instruction->base.scope, instruction->base.source_node, section_inst, false);
11701 if (type_is_invalid(section_str_inst->value->type))
11702 return ira->codegen->invalid_inst_gen;
11703 }
11704
11705 // Resolve all the comptime values
11706 Buf *symbol_name = ir_resolve_str(ira, name_inst);
11707 if (!symbol_name)
11708 return ira->codegen->invalid_inst_gen;
11709
11710 if (buf_len(symbol_name) < 1) {
11711 ir_add_error(ira, name_inst,
11712 buf_sprintf("exported symbol name cannot be empty"));
11713 return ira->codegen->invalid_inst_gen;
11714 }
11715
11716 GlobalLinkageId global_linkage_id;
11717 if (!ir_resolve_global_linkage(ira, linkage_inst, &global_linkage_id))
11718 return ira->codegen->invalid_inst_gen;
11719
11720 Buf *section_name = nullptr;
11721 if (section_str_inst != nullptr && !(section_name = ir_resolve_str(ira, section_str_inst)))
11722 return ira->codegen->invalid_inst_gen;
11723
11724 // TODO: This function needs to be audited.
11725 // It's not clear how all the different types are supposed to be handled.
11726 // Need comprehensive tests for exporting one thing in one file and declaring an extern var
11727 // in another file.
11728 TldFn *tld_fn = heap::c_allocator.create<TldFn>();
11729 tld_fn->base.id = TldIdFn;
11730 tld_fn->base.source_node = instruction->base.source_node;
11731
11732 auto entry = ira->codegen->exported_symbol_names.put_unique(symbol_name, &tld_fn->base);
11733 if (entry) {
11734 AstNode *other_export_node = entry->value->source_node;
11735 ErrorMsg *msg = ir_add_error_node(ira, instruction->base.source_node,
11736 buf_sprintf("exported symbol collision: '%s'", buf_ptr(symbol_name)));
11737 add_error_note(ira->codegen, msg, other_export_node, buf_sprintf("other symbol here"));
11738 return ira->codegen->invalid_inst_gen;
11739 }
11740
11741 Error err;
11742 bool want_var_export = false;
11743 switch (target->value->type->id) {
11744 case ZigTypeIdInvalid:
11745 case ZigTypeIdUnreachable:
11746 zig_unreachable();
11747 case ZigTypeIdFn: {
11748 assert(target->value->data.x_ptr.special == ConstPtrSpecialFunction);
11749 ZigFn *fn_entry = target->value->data.x_ptr.data.fn.fn_entry;
11750 tld_fn->fn_entry = fn_entry;
11751 CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc;
11752 switch (cc) {
11753 case CallingConventionUnspecified: {
11754 ErrorMsg *msg = ir_add_error(ira, target,
11755 buf_sprintf("exported function must specify calling convention"));
11756 add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here"));
11757 } break;
11758 case CallingConventionAsync: {
11759 ErrorMsg *msg = ir_add_error(ira, target,
11760 buf_sprintf("exported function cannot be async"));
11761 add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here"));
11762 } break;
11763 case CallingConventionInline: {
11764 ErrorMsg *msg = ir_add_error(ira, target,
11765 buf_sprintf("exported function cannot be inline"));
11766 add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here"));
11767 } break;
11768 case CallingConventionC:
11769 case CallingConventionNaked:
11770 case CallingConventionInterrupt:
11771 case CallingConventionSignal:
11772 case CallingConventionStdcall:
11773 case CallingConventionFastcall:
11774 case CallingConventionVectorcall:
11775 case CallingConventionThiscall:
11776 case CallingConventionAPCS:
11777 case CallingConventionAAPCS:
11778 case CallingConventionAAPCSVFP:
11779 case CallingConventionSysV:
11780 case CallingConventionWin64:
11781 case CallingConventionPtxKernel:
11782 case CallingConventionAmdgpuKernel:
11783 add_fn_export(ira->codegen, fn_entry, buf_ptr(symbol_name), global_linkage_id, cc);
11784 fn_entry->section_name = section_name;
11785 break;
11786 }
11787 } break;
11788 case ZigTypeIdStruct:
11789 if (is_slice(target->value->type)) {
11790 ir_add_error(ira, target,
11791 buf_sprintf("unable to export value of type '%s'", buf_ptr(&target->value->type->name)));
11792 } else if (target->value->type->data.structure.layout != ContainerLayoutExtern) {
11793 ErrorMsg *msg = ir_add_error(ira, target,
11794 buf_sprintf("exported struct value must be declared extern"));
11795 add_error_note(ira->codegen, msg, target->value->type->data.structure.decl_node, buf_sprintf("declared here"));
11796 } else {
11797 want_var_export = true;
11798 }
11799 break;
11800 case ZigTypeIdUnion:
11801 if (target->value->type->data.unionation.layout != ContainerLayoutExtern) {
11802 ErrorMsg *msg = ir_add_error(ira, target,
11803 buf_sprintf("exported union value must be declared extern"));
11804 add_error_note(ira->codegen, msg, target->value->type->data.unionation.decl_node, buf_sprintf("declared here"));
11805 } else {
11806 want_var_export = true;
11807 }
11808 break;
11809 case ZigTypeIdEnum:
11810 if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown)))
11811 return ira->codegen->invalid_inst_gen;
11812 if (!target->value->type->data.enumeration.has_explicit_tag_type) {
11813 ErrorMsg *msg = ir_add_error(ira, target,
11814 buf_sprintf("exported enum value without explicit integer tag type"));
11815 add_error_note(ira->codegen, msg, target->value->type->data.enumeration.decl_node, buf_sprintf("declared here"));
11816 } else {
11817 want_var_export = true;
11818 }
11819 break;
11820 case ZigTypeIdArray: {
11821 bool ok_type;
11822 if ((err = type_allowed_in_extern(ira->codegen, target->value->type->data.array.child_type, ExternPositionOther, &ok_type)))
11823 return ira->codegen->invalid_inst_gen;
11824
11825 if (!ok_type) {
11826 ir_add_error(ira, target,
11827 buf_sprintf("array element type '%s' not extern-compatible",
11828 buf_ptr(&target->value->type->data.array.child_type->name)));
11829 } else {
11830 want_var_export = true;
11831 }
11832 break;
11833 }
11834 case ZigTypeIdMetaType: {
11835 ZigType *type_value = target->value->data.x_type;
11836 switch (type_value->id) {
11837 case ZigTypeIdInvalid:
11838 zig_unreachable();
11839 case ZigTypeIdStruct:
11840 if (is_slice(type_value)) {
11841 ir_add_error(ira, target,
11842 buf_sprintf("unable to export type '%s'", buf_ptr(&type_value->name)));
11843 } else if (type_value->data.structure.layout != ContainerLayoutExtern) {
11844 ErrorMsg *msg = ir_add_error(ira, target,
11845 buf_sprintf("exported struct must be declared extern"));
11846 add_error_note(ira->codegen, msg, type_value->data.structure.decl_node, buf_sprintf("declared here"));
11847 }
11848 break;
11849 case ZigTypeIdUnion:
11850 if (type_value->data.unionation.layout != ContainerLayoutExtern) {
11851 ErrorMsg *msg = ir_add_error(ira, target,
11852 buf_sprintf("exported union must be declared extern"));
11853 add_error_note(ira->codegen, msg, type_value->data.unionation.decl_node, buf_sprintf("declared here"));
11854 }
11855 break;
11856 case ZigTypeIdEnum:
11857 if ((err = type_resolve(ira->codegen, type_value, ResolveStatusZeroBitsKnown)))
11858 return ira->codegen->invalid_inst_gen;
11859 if (!type_value->data.enumeration.has_explicit_tag_type) {
11860 ErrorMsg *msg = ir_add_error(ira, target,
11861 buf_sprintf("exported enum without explicit integer tag type"));
11862 add_error_note(ira->codegen, msg, type_value->data.enumeration.decl_node, buf_sprintf("declared here"));
11863 }
11864 break;
11865 case ZigTypeIdFn: {
11866 if (type_value->data.fn.fn_type_id.cc == CallingConventionUnspecified) {
11867 ir_add_error(ira, target,
11868 buf_sprintf("exported function type must specify calling convention"));
11869 }
11870 } break;
11871 case ZigTypeIdInt:
11872 case ZigTypeIdFloat:
11873 case ZigTypeIdPointer:
11874 case ZigTypeIdArray:
11875 case ZigTypeIdBool:
11876 case ZigTypeIdVector:
11877 break;
11878 case ZigTypeIdMetaType:
11879 case ZigTypeIdVoid:
11880 case ZigTypeIdUnreachable:
11881 case ZigTypeIdComptimeFloat:
11882 case ZigTypeIdComptimeInt:
11883 case ZigTypeIdEnumLiteral:
11884 case ZigTypeIdUndefined:
11885 case ZigTypeIdNull:
11886 case ZigTypeIdOptional:
11887 case ZigTypeIdErrorUnion:
11888 case ZigTypeIdErrorSet:
11889 case ZigTypeIdBoundFn:
11890 case ZigTypeIdOpaque:
11891 case ZigTypeIdFnFrame:
11892 case ZigTypeIdAnyFrame:
11893 ir_add_error(ira, target,
11894 buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name)));
11895 break;
11896 }
11897 } break;
11898 case ZigTypeIdInt:
11899 want_var_export = true;
11900 break;
11901 case ZigTypeIdVoid:
11902 case ZigTypeIdBool:
11903 case ZigTypeIdFloat:
11904 case ZigTypeIdPointer:
11905 case ZigTypeIdComptimeFloat:
11906 case ZigTypeIdComptimeInt:
11907 case ZigTypeIdUndefined:
11908 case ZigTypeIdNull:
11909 case ZigTypeIdOptional:
11910 case ZigTypeIdErrorUnion:
11911 case ZigTypeIdErrorSet:
11912 case ZigTypeIdVector:
11913 zig_panic("TODO export const value of type %s", buf_ptr(&target->value->type->name));
11914 case ZigTypeIdBoundFn:
11915 case ZigTypeIdOpaque:
11916 case ZigTypeIdEnumLiteral:
11917 case ZigTypeIdFnFrame:
11918 case ZigTypeIdAnyFrame:
11919 ir_add_error(ira, target,
11920 buf_sprintf("invalid export target type '%s'", buf_ptr(&target->value->type->name)));
11921 break;
11922 }
11923
11924 // TODO audit the various ways to use @export
11925 if (want_var_export && target->id == Stage1AirInstIdLoadPtr) {
11926 Stage1AirInstLoadPtr *load_ptr = reinterpret_cast<Stage1AirInstLoadPtr *>(target);
11927 if (load_ptr->ptr->id == Stage1AirInstIdVarPtr) {
11928 Stage1AirInstVarPtr *var_ptr = reinterpret_cast<Stage1AirInstVarPtr *>(load_ptr->ptr);
11929 ZigVar *var = var_ptr->var;
11930 add_var_export(ira->codegen, var, buf_ptr(symbol_name), global_linkage_id);
11931 var->section_name = section_name;
11932 }
11933 }
11934
11935 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
11936}
11937
11938static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, AstNode *source_node);
11939
11940static Stage1AirInst *ir_analyze_instruction_extern(IrAnalyze *ira, Stage1ZirInstExtern *instruction) {
11941 Stage1AirInst *type_inst = instruction->type->child;
11942 if (type_is_invalid(type_inst->value->type))
11943 return ira->codegen->invalid_inst_gen;
11944
11945 Stage1AirInst *options = instruction->options->child;
11946 if (type_is_invalid(options->value->type))
11947 return ira->codegen->invalid_inst_gen;
11948
11949 ZigType *options_type = options->value->type;
11950 assert(options_type->id == ZigTypeIdStruct);
11951
11952 TypeStructField *name_field = find_struct_type_field(options_type, buf_create_from_str("name"));
11953 src_assert(name_field != nullptr, instruction->base.source_node);
11954 Stage1AirInst *name_inst = ir_analyze_struct_value_field_value(ira, instruction->base.scope, instruction->base.source_node, options, name_field);
11955 if (type_is_invalid(name_inst->value->type))
11956 return ira->codegen->invalid_inst_gen;
11957
11958 TypeStructField *linkage_field = find_struct_type_field(options_type, buf_create_from_str("linkage"));
11959 src_assert(linkage_field != nullptr, instruction->base.source_node);
11960 Stage1AirInst *linkage_inst = ir_analyze_struct_value_field_value(ira, instruction->base.scope, instruction->base.source_node, options, linkage_field);
11961 if (type_is_invalid(linkage_inst->value->type))
11962 return ira->codegen->invalid_inst_gen;
11963
11964 TypeStructField *is_thread_local_field = find_struct_type_field(options_type, buf_create_from_str("is_thread_local"));
11965 src_assert(is_thread_local_field != nullptr, instruction->base.source_node);
11966 Stage1AirInst *is_thread_local_inst = ir_analyze_struct_value_field_value(ira, instruction->base.scope, instruction->base.source_node, options, is_thread_local_field);
11967 if (type_is_invalid(is_thread_local_inst->value->type))
11968 return ira->codegen->invalid_inst_gen;
11969
11970 TypeStructField *library_name_field = find_struct_type_field(options_type, buf_create_from_str("library_name"));
11971 src_assert(library_name_field != nullptr, instruction->base.source_node);
11972 Stage1AirInst *library_name_inst = ir_analyze_struct_value_field_value(ira, instruction->base.scope, instruction->base.source_node, options, library_name_field);
11973 if (type_is_invalid(library_name_inst->value->type))
11974 return ira->codegen->invalid_inst_gen;
11975
11976 // The `library_name` field is optional, we have to unwrap it first
11977 Stage1AirInst *non_null_check = ir_analyze_test_non_null(ira, instruction->base.scope, instruction->base.source_node, library_name_inst);
11978 bool is_non_null;
11979 if (!ir_resolve_bool(ira, non_null_check, &is_non_null))
11980 return ira->codegen->invalid_inst_gen;
11981
11982 Stage1AirInst *library_name_val_inst = nullptr;
11983 if (is_non_null) {
11984 library_name_val_inst = ir_analyze_optional_value_payload_value(ira, instruction->base.scope, instruction->base.source_node, library_name_inst, false);
11985 if (type_is_invalid(library_name_val_inst->value->type))
11986 return ira->codegen->invalid_inst_gen;
11987 }
11988
11989 // Resolve all the comptime values
11990 ZigType *value_type = ir_resolve_type(ira, type_inst);
11991 if (type_is_invalid(value_type))
11992 return ira->codegen->invalid_inst_gen;
11993
11994 if (get_src_ptr_type(value_type) == nullptr) {
11995 ir_add_error(ira, name_inst,
11996 buf_sprintf("expected (optional) pointer type or function"));
11997 return ira->codegen->invalid_inst_gen;
11998 }
11999
12000 Buf *symbol_name = ir_resolve_str(ira, name_inst);
12001 if (!symbol_name)
12002 return ira->codegen->invalid_inst_gen;
12003
12004 if (buf_len(symbol_name) == 0) {
12005 ir_add_error(ira, name_inst,
12006 buf_sprintf("extern symbol name cannot be empty"));
12007 return ira->codegen->invalid_inst_gen;
12008 }
12009
12010 Buf *library_name = nullptr;
12011 if (library_name_val_inst) {
12012 library_name = ir_resolve_str(ira, library_name_val_inst);
12013 if (!library_name)
12014 return ira->codegen->invalid_inst_gen;
12015
12016 if (buf_len(library_name) == 0) {
12017 ir_add_error(ira, library_name_inst,
12018 buf_sprintf("library name name cannot be empty"));
12019 return ira->codegen->invalid_inst_gen;
12020 }
12021
12022 add_link_lib_symbol(ira, library_name, symbol_name, instruction->base.source_node);
12023
12024 buf_destroy(library_name);
12025 }
12026
12027 GlobalLinkageId global_linkage_id;
12028 if (!ir_resolve_global_linkage(ira, linkage_inst, &global_linkage_id))
12029 return ira->codegen->invalid_inst_gen;
12030
12031 bool is_thread_local;
12032 if (!ir_resolve_bool(ira, is_thread_local_inst, &is_thread_local))
12033 return ira->codegen->invalid_inst_gen;
12034
12035 ZigType *expr_type = value_type;
12036 if (global_linkage_id == GlobalLinkageIdWeak && value_type->id != ZigTypeIdOptional)
12037 expr_type = get_optional_type(ira->codegen, expr_type);
12038
12039 // Create a bogus Tld object to keep track of the extern symbol.
12040 // XXX: Find a better way to do this (in stage2).
12041 TldFn *tld_fn = heap::c_allocator.create<TldFn>();
12042 tld_fn->base.id = TldIdFn;
12043 tld_fn->base.source_node = instruction->base.source_node;
12044
12045 auto entry = ira->codegen->external_symbol_names.put_unique(symbol_name, &tld_fn->base);
12046 if (entry) {
12047 AstNode *other_extern_node = entry->value->source_node;
12048 ErrorMsg *msg = ir_add_error_node(ira, instruction->base.source_node,
12049 buf_sprintf("extern symbol collision: '%s'", buf_ptr(symbol_name)));
12050 add_error_note(ira->codegen, msg, other_extern_node, buf_sprintf("other symbol here"));
12051 return ira->codegen->invalid_inst_gen;
12052 }
12053
12054 return ir_build_extern_gen(ira, instruction->base.scope, instruction->base.source_node, symbol_name, global_linkage_id,
12055 is_thread_local, expr_type);
12056}
12057
12058static bool ira_has_err_ret_trace(IrAnalyze *ira) {
12059 ZigFn *fn = ira->fn;
12060 return fn != nullptr && fn->calls_or_awaits_errorable_fn && ira->codegen->have_err_ret_tracing;
12061}
12062
12063static Stage1AirInst *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
12064 Stage1ZirInstErrorReturnTrace *instruction)
12065{
12066 ZigType *ptr_to_stack_trace_type = get_pointer_to_type(ira->codegen, get_stack_trace_type(ira->codegen), false);
12067 if (instruction->optional == IrInstErrorReturnTraceNull) {
12068 ZigType *optional_type = get_optional_type(ira->codegen, ptr_to_stack_trace_type);
12069 if (!ira_has_err_ret_trace(ira)) {
12070 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, optional_type);
12071 ZigValue *out_val = result->value;
12072 assert(get_src_ptr_type(optional_type) != nullptr);
12073 out_val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
12074 out_val->data.x_ptr.data.hard_coded_addr.addr = 0;
12075 return result;
12076 }
12077 return ir_build_error_return_trace_gen(ira, instruction->base.scope,
12078 instruction->base.source_node, instruction->optional, optional_type);
12079 } else {
12080 assert(ira->codegen->have_err_ret_tracing);
12081 return ir_build_error_return_trace_gen(ira, instruction->base.scope,
12082 instruction->base.source_node, instruction->optional, ptr_to_stack_trace_type);
12083 }
12084}
12085
12086static Stage1AirInst *ir_analyze_instruction_error_union(IrAnalyze *ira, Stage1ZirInstErrorUnion *instruction) {
12087 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_type);
12088 result->value->special = ConstValSpecialLazy;
12089
12090 LazyValueErrUnionType *lazy_err_union_type = heap::c_allocator.create<LazyValueErrUnionType>();
12091 lazy_err_union_type->ira = ira; ira_ref(ira);
12092 result->value->data.x_lazy = &lazy_err_union_type->base;
12093 lazy_err_union_type->base.id = LazyValueIdErrUnionType;
12094
12095 lazy_err_union_type->err_set_type = instruction->err_set->child;
12096 if (ir_resolve_type_lazy(ira, lazy_err_union_type->err_set_type) == nullptr)
12097 return ira->codegen->invalid_inst_gen;
12098
12099 lazy_err_union_type->payload_type = instruction->payload->child;
12100 if (ir_resolve_type_lazy(ira, lazy_err_union_type->payload_type) == nullptr)
12101 return ira->codegen->invalid_inst_gen;
12102
12103 return result;
12104}
12105
12106static Stage1AirInst *ir_analyze_alloca(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *var_type,
12107 uint32_t align, const char *name_hint, bool force_comptime)
12108{
12109 Error err;
12110
12111 ZigValue *pointee = ira->codegen->pass1_arena->create<ZigValue>();
12112 pointee->special = ConstValSpecialUndef;
12113 pointee->llvm_align = align;
12114
12115 Stage1AirInstAlloca *result = ir_build_alloca_gen(ira, scope, source_node, align, name_hint);
12116 result->base.value->special = ConstValSpecialStatic;
12117 result->base.value->data.x_ptr.special = ConstPtrSpecialRef;
12118 result->base.value->data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer;
12119 result->base.value->data.x_ptr.data.ref.pointee = pointee;
12120
12121 bool var_type_has_bits;
12122 if ((err = type_has_bits2(ira->codegen, var_type, &var_type_has_bits)))
12123 return ira->codegen->invalid_inst_gen;
12124 if (align != 0) {
12125 if ((err = type_resolve(ira->codegen, var_type, ResolveStatusAlignmentKnown)))
12126 return ira->codegen->invalid_inst_gen;
12127 if (!var_type_has_bits) {
12128 ir_add_error_node(ira, source_node,
12129 buf_sprintf("variable '%s' of zero-bit type '%s' has no in-memory representation, it cannot be aligned",
12130 name_hint, buf_ptr(&var_type->name)));
12131 return ira->codegen->invalid_inst_gen;
12132 }
12133 }
12134 assert(result->base.value->data.x_ptr.special != ConstPtrSpecialInvalid);
12135
12136 pointee->type = var_type;
12137 result->base.value->type = get_pointer_to_type_extra(ira->codegen, var_type, false, false,
12138 PtrLenSingle, align, 0, 0, false);
12139
12140 if (!force_comptime) {
12141 ZigFn *fn_entry = ira->fn;
12142 if (fn_entry != nullptr) {
12143 fn_entry->alloca_gen_list.append(result);
12144 }
12145 }
12146 return &result->base;
12147}
12148
12149static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, ResultLoc *result_loc) {
12150 switch (result_loc->id) {
12151 case ResultLocIdInvalid:
12152 case ResultLocIdPeerParent:
12153 zig_unreachable();
12154 case ResultLocIdNone:
12155 case ResultLocIdVar:
12156 case ResultLocIdBitCast:
12157 case ResultLocIdCast:
12158 return nullptr;
12159 case ResultLocIdInstruction:
12160 return result_loc->source_instruction->child->value->type;
12161 case ResultLocIdReturn:
12162 return ira->explicit_return_type;
12163 case ResultLocIdPeer:
12164 return reinterpret_cast<ResultLocPeer*>(result_loc)->parent->resolved_type;
12165 }
12166 zig_unreachable();
12167}
12168
12169static bool type_can_bit_cast(ZigType *t) {
12170 switch (t->id) {
12171 case ZigTypeIdInvalid:
12172 zig_unreachable();
12173 case ZigTypeIdMetaType:
12174 case ZigTypeIdOpaque:
12175 case ZigTypeIdBoundFn:
12176 case ZigTypeIdUnreachable:
12177 case ZigTypeIdComptimeFloat:
12178 case ZigTypeIdComptimeInt:
12179 case ZigTypeIdEnumLiteral:
12180 case ZigTypeIdUndefined:
12181 case ZigTypeIdNull:
12182 case ZigTypeIdPointer:
12183 return false;
12184 default:
12185 // TODO list these types out explicitly, there are probably some other invalid ones here
12186 return true;
12187 }
12188}
12189
12190static void set_up_result_loc_for_inferred_comptime(IrAnalyze *ira, Stage1AirInst *ptr) {
12191 ZigValue *undef_child = ira->codegen->pass1_arena->create<ZigValue>();
12192 undef_child->type = ptr->value->type->data.pointer.child_type;
12193 undef_child->special = ConstValSpecialUndef;
12194 ptr->value->special = ConstValSpecialStatic;
12195 ptr->value->data.x_ptr.mut = ConstPtrMutInfer;
12196 ptr->value->data.x_ptr.special = ConstPtrSpecialRef;
12197 ptr->value->data.x_ptr.data.ref.pointee = undef_child;
12198}
12199
12200static Error ir_result_has_type(IrAnalyze *ira, ResultLoc *result_loc, bool *out) {
12201 switch (result_loc->id) {
12202 case ResultLocIdInvalid:
12203 case ResultLocIdPeerParent:
12204 zig_unreachable();
12205 case ResultLocIdNone:
12206 case ResultLocIdPeer:
12207 *out = false;
12208 return ErrorNone;
12209 case ResultLocIdReturn:
12210 case ResultLocIdInstruction:
12211 case ResultLocIdBitCast:
12212 *out = true;
12213 return ErrorNone;
12214 case ResultLocIdCast: {
12215 ResultLocCast *result_cast = reinterpret_cast<ResultLocCast *>(result_loc);
12216 ZigType *dest_type = ir_resolve_type(ira, result_cast->base.source_instruction->child);
12217 if (type_is_invalid(dest_type))
12218 return ErrorSemanticAnalyzeFail;
12219 *out = (dest_type != ira->codegen->builtin_types.entry_anytype);
12220 return ErrorNone;
12221 }
12222 case ResultLocIdVar:
12223 *out = reinterpret_cast<ResultLocVar *>(result_loc)->var->decl_node->data.variable_declaration.type != nullptr;
12224 return ErrorNone;
12225 }
12226 zig_unreachable();
12227}
12228
12229static Stage1AirInst *ir_resolve_no_result_loc(IrAnalyze *ira, Stage1ZirInst *suspend_source_instr,
12230 ResultLoc *result_loc, ZigType *value_type)
12231{
12232 if (type_is_invalid(value_type))
12233 return ira->codegen->invalid_inst_gen;
12234 Stage1AirInstAlloca *alloca_gen = ir_build_alloca_gen(ira, suspend_source_instr->scope,
12235 suspend_source_instr->source_node, 0, "");
12236 alloca_gen->base.value->type = get_pointer_to_type_extra(ira->codegen, value_type, false, false,
12237 PtrLenSingle, 0, 0, 0, false);
12238 set_up_result_loc_for_inferred_comptime(ira, &alloca_gen->base);
12239 ZigFn *fn_entry = ira->fn;
12240 if (fn_entry != nullptr && get_scope_typeof(suspend_source_instr->scope) == nullptr) {
12241 fn_entry->alloca_gen_list.append(alloca_gen);
12242 }
12243 result_loc->written = true;
12244 result_loc->resolved_loc = &alloca_gen->base;
12245 return result_loc->resolved_loc;
12246}
12247
12248static bool result_loc_is_discard(ResultLoc *result_loc_pass1) {
12249 if (result_loc_pass1->id == ResultLocIdInstruction &&
12250 result_loc_pass1->source_instruction->id == Stage1ZirInstIdConst)
12251 {
12252 Stage1ZirInstConst *const_inst = reinterpret_cast<Stage1ZirInstConst *>(result_loc_pass1->source_instruction);
12253 if (value_is_comptime(const_inst->value) &&
12254 const_inst->value->type->id == ZigTypeIdPointer &&
12255 const_inst->value->data.x_ptr.special == ConstPtrSpecialDiscard)
12256 {
12257 return true;
12258 }
12259 }
12260 return false;
12261}
12262
12263// when calling this function, at the callsite must check for result type noreturn and propagate it up
12264static Stage1AirInst *ir_resolve_result_raw(IrAnalyze *ira, Stage1ZirInst *suspend_source_instr,
12265 ResultLoc *result_loc, ZigType *value_type, Stage1AirInst *value, bool force_runtime,
12266 bool allow_discard)
12267{
12268 Error err;
12269 if (result_loc->resolved_loc != nullptr) {
12270 // allow to redo the result location if the value is known and comptime and the previous one isn't
12271 if (value == nullptr || !instr_is_comptime(value) || instr_is_comptime(result_loc->resolved_loc)) {
12272 return result_loc->resolved_loc;
12273 }
12274 }
12275 result_loc->gen_instruction = value;
12276 result_loc->implicit_elem_type = value_type;
12277 switch (result_loc->id) {
12278 case ResultLocIdInvalid:
12279 case ResultLocIdPeerParent:
12280 zig_unreachable();
12281 case ResultLocIdNone: {
12282 if (value != nullptr) {
12283 return nullptr;
12284 }
12285 // need to return a result location and don't have one. use a stack allocation
12286 return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type);
12287 }
12288 case ResultLocIdVar: {
12289 ResultLocVar *result_loc_var = reinterpret_cast<ResultLocVar *>(result_loc);
12290 assert(result_loc->source_instruction->id == Stage1ZirInstIdAlloca);
12291 Stage1ZirInstAlloca *alloca_src = reinterpret_cast<Stage1ZirInstAlloca *>(result_loc->source_instruction);
12292
12293 ZigVar *var = result_loc_var->var;
12294 if (var->var_type != nullptr && !ir_get_var_is_comptime(var)) {
12295 // This is at least the second time we've seen this variable declaration during analysis.
12296 // This means that this is actually a different variable due to, e.g. an inline while loop.
12297 // We make a new variable so that it can hold a different type, and so the debug info can
12298 // be distinct.
12299 ZigVar *new_var = create_local_var(ira->codegen, var->decl_node, var->child_scope,
12300 buf_create_from_str(var->name), var->src_is_const, var->gen_is_const,
12301 var->shadowable, var->is_comptime, true);
12302 new_var->align_bytes = var->align_bytes;
12303
12304 var->next_var = new_var;
12305 var = new_var;
12306 }
12307 if (value_type->id == ZigTypeIdUnreachable || value_type->id == ZigTypeIdOpaque) {
12308 ir_add_error_node(ira, result_loc->source_instruction->source_node,
12309 buf_sprintf("variable of type '%s' not allowed", buf_ptr(&value_type->name)));
12310 return ira->codegen->invalid_inst_gen;
12311 }
12312 if (alloca_src->base.child == nullptr || var->ptr_instruction == nullptr) {
12313 bool force_comptime;
12314 if (!ir_resolve_comptime(ira, alloca_src->is_comptime->child, &force_comptime))
12315 return ira->codegen->invalid_inst_gen;
12316 uint32_t align = 0;
12317 if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, nullptr, &align)) {
12318 return ira->codegen->invalid_inst_gen;
12319 }
12320 Stage1AirInst *alloca_gen = ir_analyze_alloca(ira,
12321 result_loc->source_instruction->scope,
12322 result_loc->source_instruction->source_node, value_type,
12323 align, alloca_src->name_hint, force_comptime);
12324 if (force_runtime) {
12325 alloca_gen->value->data.x_ptr.mut = ConstPtrMutRuntimeVar;
12326 alloca_gen->value->special = ConstValSpecialRuntime;
12327 }
12328 if (alloca_src->base.child != nullptr && !result_loc->written) {
12329 alloca_src->base.child->ref_count = 0;
12330 }
12331 alloca_src->base.child = alloca_gen;
12332 var->ptr_instruction = alloca_gen;
12333 }
12334 result_loc->written = true;
12335 result_loc->resolved_loc = alloca_src->base.child;
12336 return alloca_src->base.child;
12337 }
12338 case ResultLocIdInstruction: {
12339 result_loc->written = true;
12340 result_loc->resolved_loc = result_loc->source_instruction->child;
12341 return result_loc->resolved_loc;
12342 }
12343 case ResultLocIdReturn: {
12344 if (value != nullptr) {
12345 reinterpret_cast<ResultLocReturn *>(result_loc)->implicit_return_type_done = true;
12346 ira->src_implicit_return_type_list.append(value);
12347 }
12348 result_loc->written = true;
12349 result_loc->resolved_loc = ira->return_ptr;
12350 return result_loc->resolved_loc;
12351 }
12352 case ResultLocIdPeer: {
12353 ResultLocPeer *result_peer = reinterpret_cast<ResultLocPeer *>(result_loc);
12354 ResultLocPeerParent *peer_parent = result_peer->parent;
12355
12356 if (peer_parent->peers.length == 1) {
12357 Stage1AirInst *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
12358 value_type, value, force_runtime, true);
12359 result_peer->suspend_pos.basic_block_index = SIZE_MAX;
12360 result_peer->suspend_pos.instruction_index = SIZE_MAX;
12361 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) ||
12362 parent_result_loc->value->type->id == ZigTypeIdUnreachable)
12363 {
12364 return parent_result_loc;
12365 }
12366 result_loc->written = true;
12367 result_loc->resolved_loc = parent_result_loc;
12368 return result_loc->resolved_loc;
12369 }
12370
12371 bool is_condition_comptime;
12372 if (!ir_resolve_comptime(ira, peer_parent->is_comptime->child, &is_condition_comptime))
12373 return ira->codegen->invalid_inst_gen;
12374 if (is_condition_comptime) {
12375 peer_parent->skipped = true;
12376 return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
12377 value_type, value, force_runtime, true);
12378 }
12379 bool peer_parent_has_type;
12380 if ((err = ir_result_has_type(ira, peer_parent->parent, &peer_parent_has_type)))
12381 return ira->codegen->invalid_inst_gen;
12382 if (peer_parent_has_type) {
12383 peer_parent->skipped = true;
12384 Stage1AirInst *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
12385 value_type, value, force_runtime || !is_condition_comptime, true);
12386 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) ||
12387 parent_result_loc->value->type->id == ZigTypeIdUnreachable)
12388 {
12389 return parent_result_loc;
12390 }
12391 peer_parent->parent->written = true;
12392 result_loc->written = true;
12393 result_loc->resolved_loc = parent_result_loc;
12394 return result_loc->resolved_loc;
12395 }
12396
12397 if (peer_parent->resolved_type == nullptr) {
12398 if (peer_parent->end_bb->suspend_instruction_ref == nullptr) {
12399 peer_parent->end_bb->suspend_instruction_ref = suspend_source_instr;
12400 }
12401 Stage1AirInst *unreach_inst = ira_suspend(ira, suspend_source_instr, result_peer->next_bb,
12402 &result_peer->suspend_pos);
12403 if (result_peer->next_bb == nullptr) {
12404 ir_start_next_bb(ira);
12405 }
12406 return unreach_inst;
12407 }
12408
12409 Stage1AirInst *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
12410 peer_parent->resolved_type, nullptr, force_runtime, true);
12411 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) ||
12412 parent_result_loc->value->type->id == ZigTypeIdUnreachable)
12413 {
12414 return parent_result_loc;
12415 }
12416 // because is_condition_comptime is false, we mark this a runtime pointer
12417 parent_result_loc->value->special = ConstValSpecialRuntime;
12418 result_loc->written = true;
12419 result_loc->resolved_loc = parent_result_loc;
12420 return result_loc->resolved_loc;
12421 }
12422 case ResultLocIdCast: {
12423 ResultLocCast *result_cast = reinterpret_cast<ResultLocCast *>(result_loc);
12424 ZigType *dest_type = ir_resolve_type(ira, result_cast->base.source_instruction->child);
12425 if (type_is_invalid(dest_type))
12426 return ira->codegen->invalid_inst_gen;
12427
12428 if (dest_type == ira->codegen->builtin_types.entry_anytype) {
12429 return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type);
12430 }
12431
12432 Stage1AirInst *casted_value;
12433 if (value != nullptr) {
12434 casted_value = ir_implicit_cast2(ira, suspend_source_instr->scope,
12435 suspend_source_instr->source_node, value, dest_type);
12436 if (type_is_invalid(casted_value->value->type))
12437 return ira->codegen->invalid_inst_gen;
12438 dest_type = casted_value->value->type;
12439 } else {
12440 casted_value = nullptr;
12441 }
12442
12443 Stage1AirInst *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_cast->parent,
12444 dest_type, casted_value, force_runtime, true);
12445 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) ||
12446 parent_result_loc->value->type->id == ZigTypeIdUnreachable)
12447 {
12448 return parent_result_loc;
12449 }
12450
12451 ZigType *parent_ptr_type = parent_result_loc->value->type;
12452 assert(parent_ptr_type->id == ZigTypeIdPointer);
12453
12454 if ((err = type_resolve(ira->codegen, parent_ptr_type->data.pointer.child_type,
12455 ResolveStatusAlignmentKnown)))
12456 {
12457 return ira->codegen->invalid_inst_gen;
12458 }
12459 uint64_t parent_ptr_align = get_ptr_align(ira->codegen, parent_ptr_type);
12460 if ((err = type_resolve(ira->codegen, value_type, ResolveStatusAlignmentKnown))) {
12461 return ira->codegen->invalid_inst_gen;
12462 }
12463 if (!type_has_bits(ira->codegen, value_type)) {
12464 parent_ptr_align = 0;
12465 }
12466 // If we're casting from a sentinel-terminated array to a non-sentinel-terminated array,
12467 // we actually need the result location pointer to *not* have a sentinel. Otherwise the generated
12468 // memcpy will write an extra byte to the destination, and THAT'S NO GOOD.
12469 ZigType *ptr_elem_type;
12470 if (value_type->id == ZigTypeIdArray && value_type->data.array.sentinel != nullptr &&
12471 dest_type->id == ZigTypeIdArray && dest_type->data.array.sentinel == nullptr)
12472 {
12473 ptr_elem_type = get_array_type(ira->codegen, value_type->data.array.child_type,
12474 value_type->data.array.len, nullptr);
12475 } else {
12476 ptr_elem_type = value_type;
12477 }
12478 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, ptr_elem_type,
12479 parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle,
12480 parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero);
12481
12482 ConstCastOnly const_cast_result = types_match_const_cast_only(ira,
12483 parent_result_loc->value->type, ptr_type,
12484 result_cast->base.source_instruction->source_node, false);
12485 if (const_cast_result.id == ConstCastResultIdInvalid)
12486 return ira->codegen->invalid_inst_gen;
12487 if (const_cast_result.id != ConstCastResultIdOk) {
12488 if (allow_discard) {
12489 return parent_result_loc;
12490 }
12491 // We will not be able to provide a result location for this value. Create
12492 // a new result location.
12493 result_cast->parent->written = false;
12494 return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type);
12495 }
12496
12497 result_loc->written = true;
12498 result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr->scope,
12499 suspend_source_instr->source_node, parent_result_loc,
12500 parent_result_loc->source_node, ptr_type,
12501 result_cast->base.source_instruction->source_node, false, false);
12502 return result_loc->resolved_loc;
12503 }
12504 case ResultLocIdBitCast: {
12505 ResultLocBitCast *result_bit_cast = reinterpret_cast<ResultLocBitCast *>(result_loc);
12506 ZigType *dest_type = ir_resolve_type(ira, result_bit_cast->base.source_instruction->child);
12507 if (type_is_invalid(dest_type))
12508 return ira->codegen->invalid_inst_gen;
12509
12510 ZigType *dest_cg_ptr_type;
12511 if ((err = get_codegen_ptr_type(ira->codegen, dest_type, &dest_cg_ptr_type)))
12512 return ira->codegen->invalid_inst_gen;
12513 if (dest_cg_ptr_type != nullptr) {
12514 ir_add_error_node(ira, result_loc->source_instruction->source_node,
12515 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
12516 return ira->codegen->invalid_inst_gen;
12517 }
12518
12519 if (!type_can_bit_cast(dest_type)) {
12520 ir_add_error_node(ira, result_loc->source_instruction->source_node,
12521 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
12522 return ira->codegen->invalid_inst_gen;
12523 }
12524
12525 ZigType *value_cg_ptr_type;
12526 if ((err = get_codegen_ptr_type(ira->codegen, value_type, &value_cg_ptr_type)))
12527 return ira->codegen->invalid_inst_gen;
12528 if (value_cg_ptr_type != nullptr) {
12529 ir_add_error_node(ira, suspend_source_instr->source_node,
12530 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&value_type->name)));
12531 return ira->codegen->invalid_inst_gen;
12532 }
12533
12534 if (!type_can_bit_cast(value_type)) {
12535 ir_add_error_node(ira, suspend_source_instr->source_node,
12536 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&value_type->name)));
12537 return ira->codegen->invalid_inst_gen;
12538 }
12539
12540 Stage1AirInst *bitcasted_value;
12541 if (value != nullptr) {
12542 bitcasted_value = ir_analyze_bit_cast(ira, result_loc->source_instruction->scope,
12543 result_loc->source_instruction->source_node, value, dest_type);
12544 dest_type = bitcasted_value->value->type;
12545 } else {
12546 bitcasted_value = nullptr;
12547 }
12548
12549 if (bitcasted_value != nullptr && type_is_invalid(bitcasted_value->value->type)) {
12550 return bitcasted_value;
12551 }
12552
12553 bool parent_was_written = result_bit_cast->parent->written;
12554 Stage1AirInst *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent,
12555 dest_type, bitcasted_value, force_runtime, true);
12556 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) ||
12557 parent_result_loc->value->type->id == ZigTypeIdUnreachable)
12558 {
12559 return parent_result_loc;
12560 }
12561 ZigType *parent_ptr_type = parent_result_loc->value->type;
12562 assert(parent_ptr_type->id == ZigTypeIdPointer);
12563 ZigType *child_type = parent_ptr_type->data.pointer.child_type;
12564
12565 if (result_loc_is_discard(result_bit_cast->parent)) {
12566 assert(allow_discard);
12567 return parent_result_loc;
12568 }
12569
12570 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown))) {
12571 return ira->codegen->invalid_inst_gen;
12572 }
12573
12574 if ((err = type_resolve(ira->codegen, value_type, ResolveStatusSizeKnown))) {
12575 return ira->codegen->invalid_inst_gen;
12576 }
12577
12578 if (child_type != ira->codegen->builtin_types.entry_anytype) {
12579 if (type_size(ira->codegen, child_type) != type_size(ira->codegen, value_type)) {
12580 // pointer cast won't work; we need a temporary location.
12581 result_bit_cast->parent->written = parent_was_written;
12582 result_loc->written = true;
12583 result_loc->resolved_loc = ir_resolve_result(ira, suspend_source_instr, no_result_loc(),
12584 value_type, bitcasted_value, force_runtime, true);
12585 return result_loc->resolved_loc;
12586 }
12587 }
12588 uint64_t parent_ptr_align = 0;
12589 if (type_has_bits(ira->codegen, value_type)) parent_ptr_align = get_ptr_align(ira->codegen, parent_ptr_type);
12590 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value_type,
12591 parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle,
12592 parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero);
12593
12594 result_loc->written = true;
12595 result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr->scope,
12596 suspend_source_instr->source_node, parent_result_loc,
12597 parent_result_loc->source_node, ptr_type,
12598 result_bit_cast->base.source_instruction->source_node, false, false);
12599 return result_loc->resolved_loc;
12600 }
12601 }
12602 zig_unreachable();
12603}
12604
12605static Stage1AirInst *ir_resolve_result(IrAnalyze *ira, Stage1ZirInst *suspend_source_instr,
12606 ResultLoc *result_loc_pass1, ZigType *value_type, Stage1AirInst *value, bool force_runtime,
12607 bool allow_discard)
12608{
12609 if (!allow_discard && result_loc_is_discard(result_loc_pass1)) {
12610 result_loc_pass1 = no_result_loc();
12611 }
12612 bool was_written = result_loc_pass1->written;
12613 Stage1AirInst *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type,
12614 value, force_runtime, allow_discard);
12615 if (result_loc == nullptr || result_loc->value->type->id == ZigTypeIdUnreachable ||
12616 type_is_invalid(result_loc->value->type))
12617 {
12618 return result_loc;
12619 }
12620
12621 if ((force_runtime || (value != nullptr && !instr_is_comptime(value))) &&
12622 result_loc_pass1->written && result_loc->value->data.x_ptr.mut == ConstPtrMutInfer)
12623 {
12624 result_loc->value->special = ConstValSpecialRuntime;
12625 }
12626
12627 InferredStructField *isf = result_loc->value->type->data.pointer.inferred_struct_field;
12628 if (isf != nullptr) {
12629 TypeStructField *field;
12630 Stage1AirInst *casted_ptr;
12631 if (isf->already_resolved) {
12632 field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
12633 casted_ptr = result_loc;
12634 } else {
12635 isf->already_resolved = true;
12636 // Now it's time to add the field to the struct type.
12637 uint32_t old_field_count = isf->inferred_struct_type->data.structure.src_field_count;
12638 uint32_t new_field_count = old_field_count + 1;
12639 isf->inferred_struct_type->data.structure.src_field_count = new_field_count;
12640 isf->inferred_struct_type->data.structure.fields = realloc_type_struct_fields(
12641 isf->inferred_struct_type->data.structure.fields, old_field_count, new_field_count);
12642
12643 field = isf->inferred_struct_type->data.structure.fields[old_field_count];
12644 field->name = isf->field_name;
12645 field->type_entry = value_type;
12646 field->type_val = create_const_type(ira->codegen, field->type_entry);
12647 field->src_index = old_field_count;
12648 field->decl_node = value ? value->source_node : suspend_source_instr->source_node;
12649 if (value && instr_is_comptime(value)) {
12650 ZigValue *val = ir_resolve_const(ira, value, UndefOk);
12651 if (!val)
12652 return ira->codegen->invalid_inst_gen;
12653 field->is_comptime = true;
12654 field->init_val = ira->codegen->pass1_arena->create<ZigValue>();
12655 copy_const_val(ira->codegen, field->init_val, val);
12656 return result_loc;
12657 }
12658
12659 ZigType *struct_ptr_type = get_pointer_to_type(ira->codegen, isf->inferred_struct_type, false);
12660 if (instr_is_comptime(result_loc)) {
12661 casted_ptr = ir_const(ira, suspend_source_instr->scope,
12662 suspend_source_instr->source_node, struct_ptr_type);
12663 copy_const_val(ira->codegen, casted_ptr->value, result_loc->value);
12664 casted_ptr->value->type = struct_ptr_type;
12665 } else {
12666 casted_ptr = result_loc;
12667 }
12668 if (instr_is_comptime(casted_ptr)) {
12669 ZigValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad);
12670 if (!ptr_val)
12671 return ira->codegen->invalid_inst_gen;
12672 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
12673 ZigValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val,
12674 suspend_source_instr->source_node);
12675 struct_val->special = ConstValSpecialStatic;
12676 struct_val->data.x_struct.fields = realloc_const_vals_ptrs(ira->codegen,
12677 struct_val->data.x_struct.fields, old_field_count, new_field_count);
12678
12679 ZigValue *field_val = struct_val->data.x_struct.fields[old_field_count];
12680 field_val->special = ConstValSpecialUndef;
12681 field_val->type = field->type_entry;
12682 field_val->parent.id = ConstParentIdStruct;
12683 field_val->parent.data.p_struct.struct_val = struct_val;
12684 field_val->parent.data.p_struct.field_index = old_field_count;
12685 }
12686 }
12687 }
12688
12689 result_loc = ir_analyze_struct_field_ptr(ira, suspend_source_instr->scope,
12690 suspend_source_instr->source_node, field, casted_ptr,
12691 isf->inferred_struct_type, true);
12692 if (type_is_invalid(result_loc->value->type)) {
12693 return result_loc;
12694 }
12695 result_loc_pass1->resolved_loc = result_loc;
12696 }
12697
12698 if (was_written) {
12699 return result_loc;
12700 }
12701
12702 src_assert(result_loc->value->type->id == ZigTypeIdPointer, suspend_source_instr->source_node);
12703 ZigType *actual_elem_type = result_loc->value->type->data.pointer.child_type;
12704 if (actual_elem_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
12705 value_type->id != ZigTypeIdNull && value_type->id != ZigTypeIdUndefined)
12706 {
12707 bool same_comptime_repr = types_have_same_zig_comptime_repr(ira->codegen, actual_elem_type, value_type);
12708 if (!same_comptime_repr) {
12709 result_loc_pass1->written = was_written;
12710 return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr->scope,
12711 suspend_source_instr->source_node, result_loc, false, true);
12712 }
12713 } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion &&
12714 value_type->id != ZigTypeIdUndefined)
12715 {
12716 if (value_type->id == ZigTypeIdErrorSet) {
12717 return ir_analyze_unwrap_err_code(ira, suspend_source_instr->scope,
12718 suspend_source_instr->source_node, result_loc, true);
12719 } else {
12720 Stage1AirInst *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira,
12721 suspend_source_instr->scope, suspend_source_instr->source_node,
12722 result_loc, false, true);
12723 ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type;
12724 if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
12725 value_type->id != ZigTypeIdNull && value_type->id != ZigTypeIdUndefined)
12726 {
12727 return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr->scope,
12728 suspend_source_instr->source_node, unwrapped_err_ptr, false, true);
12729 } else {
12730 return unwrapped_err_ptr;
12731 }
12732 }
12733 }
12734 return result_loc;
12735}
12736
12737static Stage1AirInst *ir_analyze_instruction_resolve_result(IrAnalyze *ira, Stage1ZirInstResolveResult *instruction) {
12738 ZigType *implicit_elem_type;
12739 if (instruction->ty == nullptr) {
12740 if (instruction->result_loc->id == ResultLocIdCast) {
12741 implicit_elem_type = ir_resolve_type(ira,
12742 instruction->result_loc->source_instruction->child);
12743 if (type_is_invalid(implicit_elem_type))
12744 return ira->codegen->invalid_inst_gen;
12745 } else if (instruction->result_loc->id == ResultLocIdReturn) {
12746 implicit_elem_type = ira->explicit_return_type;
12747 if (type_is_invalid(implicit_elem_type))
12748 return ira->codegen->invalid_inst_gen;
12749 } else {
12750 implicit_elem_type = ira->codegen->builtin_types.entry_anytype;
12751 }
12752 if (implicit_elem_type == ira->codegen->builtin_types.entry_anytype) {
12753 Buf *bare_name = buf_alloc();
12754 Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
12755 instruction->base.scope, instruction->base.source_node, bare_name, nullptr);
12756
12757 StructSpecial struct_special = StructSpecialInferredStruct;
12758 if (instruction->base.source_node->type == NodeTypeContainerInitExpr &&
12759 instruction->base.source_node->data.container_init_expr.kind == ContainerInitKindArray)
12760 {
12761 struct_special = StructSpecialInferredTuple;
12762 }
12763
12764 ZigType *inferred_struct_type = get_partial_container_type(ira->codegen,
12765 instruction->base.scope, ContainerKindStruct, instruction->base.source_node,
12766 buf_ptr(name), bare_name, ContainerLayoutAuto);
12767 inferred_struct_type->data.structure.special = struct_special;
12768 inferred_struct_type->data.structure.resolve_status = ResolveStatusBeingInferred;
12769 implicit_elem_type = inferred_struct_type;
12770 }
12771 } else {
12772 implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);
12773 if (type_is_invalid(implicit_elem_type))
12774 return ira->codegen->invalid_inst_gen;
12775 }
12776 Stage1AirInst *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
12777 implicit_elem_type, nullptr, false, true);
12778 if (result_loc != nullptr)
12779 return result_loc;
12780
12781 ZigFn *fn = ira->fn;
12782 if (fn != nullptr && fn->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync &&
12783 instruction->result_loc->id == ResultLocIdReturn)
12784 {
12785 result_loc = ir_resolve_result(ira, &instruction->base, no_result_loc(),
12786 implicit_elem_type, nullptr, false, true);
12787 if (result_loc != nullptr &&
12788 (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable))
12789 {
12790 return result_loc;
12791 }
12792 result_loc->value->special = ConstValSpecialRuntime;
12793 return result_loc;
12794 }
12795
12796 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, implicit_elem_type);
12797 result->value->special = ConstValSpecialUndef;
12798 Stage1AirInst *ptr = ir_get_ref(ira, instruction->base.scope, instruction->base.source_node, result, false, false);
12799 ptr->value->data.x_ptr.mut = ConstPtrMutComptimeVar;
12800 return ptr;
12801}
12802
12803static void ir_reset_result(ResultLoc *result_loc) {
12804 result_loc->written = false;
12805 result_loc->resolved_loc = nullptr;
12806 result_loc->gen_instruction = nullptr;
12807 result_loc->implicit_elem_type = nullptr;
12808 switch (result_loc->id) {
12809 case ResultLocIdInvalid:
12810 zig_unreachable();
12811 case ResultLocIdPeerParent: {
12812 ResultLocPeerParent *peer_parent = reinterpret_cast<ResultLocPeerParent *>(result_loc);
12813 peer_parent->skipped = false;
12814 peer_parent->done_resuming = false;
12815 peer_parent->resolved_type = nullptr;
12816 for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
12817 ir_reset_result(&peer_parent->peers.at(i)->base);
12818 }
12819 break;
12820 }
12821 case ResultLocIdVar: {
12822 Stage1ZirInstAlloca *alloca_src = reinterpret_cast<Stage1ZirInstAlloca *>(result_loc->source_instruction);
12823 alloca_src->base.child = nullptr;
12824 break;
12825 }
12826 case ResultLocIdReturn:
12827 reinterpret_cast<ResultLocReturn *>(result_loc)->implicit_return_type_done = false;
12828 break;
12829 case ResultLocIdPeer:
12830 case ResultLocIdNone:
12831 case ResultLocIdInstruction:
12832 case ResultLocIdBitCast:
12833 case ResultLocIdCast:
12834 break;
12835 }
12836}
12837
12838static Stage1AirInst *ir_analyze_instruction_reset_result(IrAnalyze *ira, Stage1ZirInstResetResult *instruction) {
12839 ir_reset_result(instruction->result_loc);
12840 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
12841}
12842
12843static Stage1AirInst *get_async_call_result_loc(IrAnalyze *ira, Scope *scope, AstNode *source_node,
12844 ZigType *fn_ret_type, bool is_async_call_builtin, Stage1AirInst **args_ptr, size_t args_len,
12845 Stage1AirInst *ret_ptr_uncasted)
12846{
12847 src_assert(is_async_call_builtin, source_node);
12848 if (type_is_invalid(ret_ptr_uncasted->value->type))
12849 return ira->codegen->invalid_inst_gen;
12850 if (ret_ptr_uncasted->value->type->id == ZigTypeIdVoid) {
12851 // Result location will be inside the async frame.
12852 return nullptr;
12853 }
12854 return ir_implicit_cast(ira, ret_ptr_uncasted, get_pointer_to_type(ira->codegen, fn_ret_type, false));
12855}
12856
12857static Stage1AirInst *ir_analyze_async_call(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigFn *fn_entry,
12858 ZigType *fn_type, Stage1AirInst *fn_ref, Stage1AirInst **casted_args, size_t arg_count,
12859 Stage1AirInst *casted_new_stack, bool is_async_call_builtin, Stage1AirInst *ret_ptr_uncasted,
12860 ResultLoc *call_result_loc)
12861{
12862 if (fn_entry == nullptr) {
12863 if (fn_type->data.fn.fn_type_id.cc != CallingConventionAsync) {
12864 ir_add_error(ira, fn_ref,
12865 buf_sprintf("expected async function, found '%s'", buf_ptr(&fn_type->name)));
12866 return ira->codegen->invalid_inst_gen;
12867 }
12868 if (casted_new_stack == nullptr) {
12869 ir_add_error(ira, fn_ref, buf_sprintf("function is not comptime-known; @asyncCall required"));
12870 return ira->codegen->invalid_inst_gen;
12871 }
12872 }
12873 if (casted_new_stack != nullptr) {
12874 ZigType *fn_ret_type = fn_type->data.fn.fn_type_id.return_type;
12875 Stage1AirInst *ret_ptr = get_async_call_result_loc(ira, scope, source_node, fn_ret_type, is_async_call_builtin,
12876 casted_args, arg_count, ret_ptr_uncasted);
12877 if (ret_ptr != nullptr && type_is_invalid(ret_ptr->value->type))
12878 return ira->codegen->invalid_inst_gen;
12879
12880 ZigType *anyframe_type = get_any_frame_type(ira->codegen, fn_ret_type);
12881
12882 Stage1AirInstCall *call_gen = ir_build_call_gen(ira, scope, source_node, fn_entry, fn_ref,
12883 arg_count, casted_args, CallModifierAsync, casted_new_stack,
12884 is_async_call_builtin, ret_ptr, anyframe_type);
12885 return &call_gen->base;
12886 } else {
12887 ZigType *frame_type = get_fn_frame_type(ira->codegen, fn_entry);
12888 Stage1AirInst *result_loc = ir_resolve_result(ira, ira->suspend_source_instr, call_result_loc,
12889 frame_type, nullptr, true, false);
12890 if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
12891 return result_loc;
12892 }
12893 result_loc = ir_implicit_cast2(ira, scope, source_node, result_loc,
12894 get_pointer_to_type(ira->codegen, frame_type, false));
12895 if (type_is_invalid(result_loc->value->type))
12896 return ira->codegen->invalid_inst_gen;
12897 return &ir_build_call_gen(ira, scope, source_node, fn_entry, fn_ref, arg_count,
12898 casted_args, CallModifierAsync, casted_new_stack,
12899 is_async_call_builtin, result_loc, frame_type)->base;
12900 }
12901}
12902static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
12903 Stage1AirInst *arg, Scope **exec_scope, size_t *next_proto_i)
12904{
12905 AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(*next_proto_i);
12906 assert(param_decl_node->type == NodeTypeParamDecl);
12907
12908 Stage1AirInst *casted_arg;
12909 if (param_decl_node->data.param_decl.anytype_token == 0) {
12910 AstNode *param_type_node = param_decl_node->data.param_decl.type;
12911 ZigType *param_type = ir_analyze_type_expr(ira, *exec_scope, param_type_node);
12912 if (type_is_invalid(param_type))
12913 return false;
12914
12915 casted_arg = ir_implicit_cast(ira, arg, param_type);
12916 if (type_is_invalid(casted_arg->value->type))
12917 return false;
12918 } else {
12919 casted_arg = arg;
12920 }
12921
12922 ZigValue *arg_val = ir_resolve_const(ira, casted_arg, UndefOk);
12923 if (!arg_val)
12924 return false;
12925
12926 Buf *param_name = param_decl_node->data.param_decl.name;
12927 ZigVar *var = add_variable(ira->codegen, param_decl_node,
12928 *exec_scope, param_name, true, arg_val, nullptr, arg_val->type);
12929 *exec_scope = var->child_scope;
12930 *next_proto_i += 1;
12931
12932 return true;
12933}
12934
12935static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_node,
12936 Stage1AirInst *arg, AstNode *arg_src, Scope **child_scope, size_t *next_proto_i,
12937 GenericFnTypeId *generic_id, FnTypeId *fn_type_id, Stage1AirInst **casted_args,
12938 ZigFn *impl_fn)
12939{
12940 AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(*next_proto_i);
12941 assert(param_decl_node->type == NodeTypeParamDecl);
12942 bool is_var_args = param_decl_node->data.param_decl.is_var_args;
12943 bool arg_part_of_generic_id = false;
12944 Stage1AirInst *casted_arg;
12945
12946 ZigType *param_info_type = nullptr;
12947 if (is_var_args) {
12948 arg_part_of_generic_id = true;
12949 casted_arg = arg;
12950 param_info_type = arg->value->type;
12951 } else {
12952 if (param_decl_node->data.param_decl.anytype_token == 0) {
12953 AstNode *param_type_node = param_decl_node->data.param_decl.type;
12954 ZigType *param_type = ir_analyze_type_expr(ira, *child_scope, param_type_node);
12955 if (type_is_invalid(param_type))
12956 return false;
12957
12958 casted_arg = ir_implicit_cast2(ira, arg->scope, arg_src, arg, param_type);
12959 if (type_is_invalid(casted_arg->value->type))
12960 return false;
12961
12962 param_info_type = param_type;
12963 } else {
12964 arg_part_of_generic_id = true;
12965 casted_arg = arg;
12966 param_info_type = arg->value->type;
12967 }
12968 }
12969
12970 bool comptime_arg = param_decl_node->data.param_decl.is_comptime;
12971 if (!comptime_arg) {
12972 switch (type_requires_comptime(ira->codegen, casted_arg->value->type)) {
12973 case ReqCompTimeInvalid:
12974 return false;
12975 case ReqCompTimeYes:
12976 comptime_arg = true;
12977 break;
12978 case ReqCompTimeNo:
12979 break;
12980 }
12981 }
12982
12983 ZigValue *arg_val;
12984
12985 if (comptime_arg && !instr_is_comptime(casted_arg)) {
12986 ir_add_error(ira, casted_arg,
12987 buf_sprintf("runtime value cannot be passed to comptime arg"));
12988 return false;
12989 }
12990 if (comptime_arg) {
12991 arg_part_of_generic_id = true;
12992 arg_val = ir_resolve_const(ira, casted_arg, UndefBad);
12993 if (!arg_val)
12994 return false;
12995 } else {
12996 arg_val = create_const_runtime(ira->codegen, casted_arg->value->type);
12997 }
12998 if (arg_part_of_generic_id) {
12999 copy_const_val(ira->codegen, &generic_id->params[generic_id->param_count], arg_val);
13000 generic_id->param_count += 1;
13001 }
13002
13003 Buf *param_name = param_decl_node->data.param_decl.name;
13004 if (!param_name) return false;
13005 if (!is_var_args) {
13006 ZigVar *var = add_variable(ira->codegen, param_decl_node,
13007 *child_scope, param_name, true, arg_val, nullptr, arg_val->type);
13008 *child_scope = var->child_scope;
13009 var->shadowable = !comptime_arg;
13010
13011 *next_proto_i += 1;
13012 } else if (casted_arg->value->type->id == ZigTypeIdComptimeInt ||
13013 casted_arg->value->type->id == ZigTypeIdComptimeFloat)
13014 {
13015 ir_add_error(ira, casted_arg,
13016 buf_sprintf("compiler bug: integer and float literals in var args function must be casted. https://github.com/ziglang/zig/issues/557"));
13017 return false;
13018 }
13019
13020 if (!comptime_arg) {
13021 casted_args[fn_type_id->param_count] = casted_arg;
13022 FnTypeParamInfo *param_info = &fn_type_id->param_info[fn_type_id->param_count];
13023 param_info->type = param_info_type;
13024 param_info->is_noalias = param_decl_node->data.param_decl.is_noalias;
13025 impl_fn->param_source_nodes[fn_type_id->param_count] = param_decl_node;
13026 fn_type_id->param_count += 1;
13027 }
13028
13029 return true;
13030}
13031
13032static Stage1AirInst *ir_get_var_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigVar *var) {
13033 while (var->next_var != nullptr) {
13034 var = var->next_var;
13035 }
13036
13037 if (var->var_type == nullptr || type_is_invalid(var->var_type))
13038 return ira->codegen->invalid_inst_gen;
13039
13040 bool is_volatile = false;
13041 ZigType *var_ptr_type = get_pointer_to_type_extra(ira->codegen, var->var_type,
13042 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0, false);
13043
13044 if (var->ptr_instruction != nullptr) {
13045 return ir_implicit_cast(ira, var->ptr_instruction, var_ptr_type);
13046 }
13047
13048 bool comptime_var_mem = ir_get_var_is_comptime(var);
13049 bool linkage_makes_it_runtime = var->decl_node->data.variable_declaration.is_extern;
13050
13051 Stage1AirInst *result = ir_build_var_ptr_gen(ira, scope, source_node, var);
13052 result->value->type = var_ptr_type;
13053
13054 if (!linkage_makes_it_runtime && !var->is_thread_local && value_is_comptime(var->const_value)) {
13055 ZigValue *val = var->const_value;
13056 switch (val->special) {
13057 case ConstValSpecialRuntime:
13058 break;
13059 case ConstValSpecialStatic: // fallthrough
13060 case ConstValSpecialLazy: // fallthrough
13061 case ConstValSpecialUndef: {
13062 ConstPtrMut ptr_mut;
13063 if (comptime_var_mem) {
13064 ptr_mut = ConstPtrMutComptimeVar;
13065 } else if (var->gen_is_const) {
13066 ptr_mut = ConstPtrMutComptimeConst;
13067 } else {
13068 assert(!comptime_var_mem);
13069 ptr_mut = ConstPtrMutRuntimeVar;
13070 }
13071 result->value->special = ConstValSpecialStatic;
13072 result->value->data.x_ptr.mut = ptr_mut;
13073 result->value->data.x_ptr.special = ConstPtrSpecialRef;
13074 result->value->data.x_ptr.data.ref.pointee = val;
13075 return result;
13076 }
13077 }
13078 }
13079
13080 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
13081 result->value->data.rh_ptr = in_fn_scope ? RuntimeHintPtrStack : RuntimeHintPtrNonStack;
13082
13083 return result;
13084}
13085
13086// This function is called when a comptime value becomes accessible at runtime.
13087static void mark_comptime_value_escape(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigValue *val) {
13088 src_assert(value_is_comptime(val), source_node);
13089 if (val->special == ConstValSpecialUndef)
13090 return;
13091
13092 if (val->type->id == ZigTypeIdFn && val->type->data.fn.fn_type_id.cc == CallingConventionUnspecified) {
13093 src_assert(val->data.x_ptr.special == ConstPtrSpecialFunction, source_node);
13094 if (val->data.x_ptr.data.fn.fn_entry->non_async_node == nullptr) {
13095 val->data.x_ptr.data.fn.fn_entry->non_async_node = source_node;
13096 }
13097 }
13098}
13099
13100static Stage1AirInst *ir_analyze_store_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node,
13101 Stage1AirInst *ptr, Stage1AirInst *uncasted_value, bool allow_write_through_const)
13102{
13103 assert(ptr->value->type->id == ZigTypeIdPointer);
13104
13105 if (ptr->value->data.x_ptr.special == ConstPtrSpecialDiscard) {
13106 if (uncasted_value->value->type->id == ZigTypeIdErrorUnion ||
13107 uncasted_value->value->type->id == ZigTypeIdErrorSet)
13108 {
13109 ir_add_error_node(ira, source_node, buf_sprintf("error is discarded. consider using `try`, `catch`, or `if`"));
13110 return ira->codegen->invalid_inst_gen;
13111 }
13112 return ir_const_void(ira, scope, source_node);
13113 }
13114
13115 if (ptr->value->type->data.pointer.is_const && !allow_write_through_const) {
13116 ir_add_error_node(ira, source_node, buf_sprintf("cannot assign to constant"));
13117 return ira->codegen->invalid_inst_gen;
13118 }
13119
13120 ZigType *child_type = ptr->value->type->data.pointer.child_type;
13121 Stage1AirInst *value = ir_implicit_cast(ira, uncasted_value, child_type);
13122 if (type_is_invalid(value->value->type))
13123 return ira->codegen->invalid_inst_gen;
13124
13125 switch (type_has_one_possible_value(ira->codegen, child_type)) {
13126 case OnePossibleValueInvalid:
13127 return ira->codegen->invalid_inst_gen;
13128 case OnePossibleValueYes:
13129 return ir_const_void(ira, scope, source_node);
13130 case OnePossibleValueNo:
13131 break;
13132 }
13133
13134 if (instr_is_comptime(ptr) && ptr->value->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
13135 if (!allow_write_through_const && ptr->value->data.x_ptr.mut == ConstPtrMutComptimeConst) {
13136 ir_add_error_node(ira, source_node, buf_sprintf("cannot assign to constant"));
13137 return ira->codegen->invalid_inst_gen;
13138 }
13139 if ((allow_write_through_const && ptr->value->data.x_ptr.mut == ConstPtrMutComptimeConst) ||
13140 ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar ||
13141 ptr->value->data.x_ptr.mut == ConstPtrMutInfer)
13142 {
13143 if (instr_is_comptime(value)) {
13144 ZigValue *dest_val = const_ptr_pointee(ira, ira->codegen, ptr->value, source_node);
13145 if (dest_val == nullptr)
13146 return ira->codegen->invalid_inst_gen;
13147 if (dest_val->special != ConstValSpecialRuntime) {
13148 copy_const_val(ira->codegen, dest_val, value->value);
13149
13150 if (ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar &&
13151 ira->new_irb.current_basic_block->must_be_comptime_source_node == nullptr)
13152 {
13153 ira->new_irb.current_basic_block->must_be_comptime_source_node = source_node;
13154 }
13155 return ir_const_void(ira, scope, source_node);
13156 }
13157 }
13158 if (ptr->value->data.x_ptr.mut == ConstPtrMutInfer) {
13159 ptr->value->special = ConstValSpecialRuntime;
13160 } else {
13161 ir_add_error_node(ira, source_node,
13162 buf_sprintf("cannot store runtime value in compile time variable"));
13163 ZigValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, ptr->value);
13164 dest_val->type = ira->codegen->builtin_types.entry_invalid;
13165
13166 return ira->codegen->invalid_inst_gen;
13167 }
13168 }
13169 }
13170
13171 if (ptr->value->type->data.pointer.inferred_struct_field != nullptr &&
13172 child_type == ira->codegen->builtin_types.entry_anytype)
13173 {
13174 child_type = ptr->value->type->data.pointer.inferred_struct_field->inferred_struct_type;
13175 }
13176
13177 switch (type_requires_comptime(ira->codegen, child_type)) {
13178 case ReqCompTimeInvalid:
13179 return ira->codegen->invalid_inst_gen;
13180 case ReqCompTimeYes:
13181 switch (type_has_one_possible_value(ira->codegen, ptr->value->type)) {
13182 case OnePossibleValueInvalid:
13183 return ira->codegen->invalid_inst_gen;
13184 case OnePossibleValueNo:
13185 ir_add_error_node(ira, source_node,
13186 buf_sprintf("cannot store runtime value in type '%s'", buf_ptr(&child_type->name)));
13187 return ira->codegen->invalid_inst_gen;
13188 case OnePossibleValueYes:
13189 return ir_const_void(ira, scope, source_node);
13190 }
13191 zig_unreachable();
13192 case ReqCompTimeNo:
13193 break;
13194 }
13195
13196 if (instr_is_comptime(value)) {
13197 mark_comptime_value_escape(ira, scope, source_node, value->value);
13198 }
13199
13200 // If this is a store to a pointer with a runtime-known vector index,
13201 // we have to figure out the Stage1AirInst which represents the index and
13202 // emit a Stage1AirInstVectorStoreElem, or emit a compile error
13203 // explaining why it is impossible for this store to work. Which is that
13204 // the pointer address is of the vector; without the element index being known
13205 // we cannot properly perform the insertion.
13206 if (ptr->value->type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) {
13207 if (ptr->id == Stage1AirInstIdElemPtr) {
13208 Stage1AirInstElemPtr *elem_ptr = (Stage1AirInstElemPtr *)ptr;
13209 return ir_build_vector_store_elem(ira, scope, source_node, elem_ptr->array_ptr,
13210 elem_ptr->elem_index, value);
13211 }
13212 ir_add_error(ira, ptr,
13213 buf_sprintf("unable to determine vector element index of type '%s'",
13214 buf_ptr(&ptr->value->type->name)));
13215 return ira->codegen->invalid_inst_gen;
13216 }
13217
13218 return ir_build_store_ptr_gen(ira, scope, source_node, ptr, value);
13219}
13220
13221static Stage1AirInst *analyze_casted_new_stack(IrAnalyze *ira, Scope *scope, AstNode *source_node,
13222 Stage1AirInst *new_stack, AstNode *new_stack_src, bool is_async_call_builtin, ZigFn *fn_entry)
13223{
13224 if (new_stack == nullptr)
13225 return nullptr;
13226
13227 if (!is_async_call_builtin &&
13228 arch_stack_pointer_register_name(ira->codegen->zig_target->arch) == nullptr)
13229 {
13230 ir_add_error_node(ira, source_node,
13231 buf_sprintf("target arch '%s' does not support calling with a new stack",
13232 target_arch_name(ira->codegen->zig_target->arch)));
13233 }
13234
13235 if (is_async_call_builtin &&
13236 fn_entry != nullptr && new_stack->value->type->id == ZigTypeIdPointer &&
13237 new_stack->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame)
13238 {
13239 ZigType *needed_frame_type = get_pointer_to_type(ira->codegen,
13240 get_fn_frame_type(ira->codegen, fn_entry), false);
13241 return ir_implicit_cast(ira, new_stack, needed_frame_type);
13242 } else {
13243 // XXX The stack alignment is hardcoded to 16 here and in
13244 // std.Target.stack_align.
13245 const uint32_t required_align = is_async_call_builtin ?
13246 get_async_frame_align_bytes(ira->codegen) : 16;
13247 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
13248 false, false, PtrLenUnknown, required_align, 0, 0, false);
13249 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
13250 ira->codegen->need_frame_size_prefix_data = true;
13251 return ir_implicit_cast2(ira, new_stack->scope, new_stack_src, new_stack, u8_slice);
13252 }
13253}
13254
13255static Stage1AirInst *ir_analyze_fn_call(IrAnalyze *ira, Scope *scope, AstNode *source_node,
13256 ZigFn *fn_entry, ZigType *fn_type, Stage1AirInst *fn_ref,
13257 Stage1AirInst *first_arg_ptr, AstNode *first_arg_ptr_src, CallModifier modifier,
13258 Stage1AirInst *new_stack, AstNode *new_stack_src, bool is_async_call_builtin,
13259 Stage1AirInst **args_ptr, size_t args_len, Stage1AirInst *ret_ptr, ResultLoc *call_result_loc)
13260{
13261 Error err;
13262 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
13263 size_t first_arg_1_or_0 = first_arg_ptr ? 1 : 0;
13264
13265 // for extern functions, the var args argument is not counted.
13266 // for zig functions, it is.
13267 size_t var_args_1_or_0;
13268 if (fn_type_id->cc == CallingConventionC) {
13269 var_args_1_or_0 = 0;
13270 } else {
13271 var_args_1_or_0 = fn_type_id->is_var_args ? 1 : 0;
13272 }
13273 size_t src_param_count = fn_type_id->param_count - var_args_1_or_0;
13274 size_t call_param_count = args_len + first_arg_1_or_0;
13275
13276 AstNode *fn_proto_node = fn_entry ? fn_entry->proto_node : nullptr;;
13277
13278 if (fn_type_id->cc == CallingConventionNaked) {
13279 ErrorMsg *msg = ir_add_error(ira, fn_ref, buf_sprintf("unable to call function with naked calling convention"));
13280 if (fn_proto_node) {
13281 add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("declared here"));
13282 }
13283 return ira->codegen->invalid_inst_gen;
13284 }
13285
13286 if (fn_type_id->is_var_args) {
13287 if (call_param_count < src_param_count) {
13288 ErrorMsg *msg = ir_add_error_node(ira, source_node,
13289 buf_sprintf("expected at least %" ZIG_PRI_usize " argument(s), found %" ZIG_PRI_usize "",
13290 src_param_count, call_param_count));
13291 if (fn_proto_node) {
13292 add_error_note(ira->codegen, msg, fn_proto_node,
13293 buf_sprintf("declared here"));
13294 }
13295 return ira->codegen->invalid_inst_gen;
13296 }
13297 } else if (src_param_count != call_param_count) {
13298 ErrorMsg *msg = ir_add_error_node(ira, source_node,
13299 buf_sprintf("expected %" ZIG_PRI_usize " argument(s), found %" ZIG_PRI_usize "",
13300 src_param_count, call_param_count));
13301 if (fn_proto_node) {
13302 add_error_note(ira->codegen, msg, fn_proto_node,
13303 buf_sprintf("declared here"));
13304 }
13305 return ira->codegen->invalid_inst_gen;
13306 }
13307
13308 if (modifier == CallModifierCompileTime) {
13309 // If we are evaluating an extern function in a TypeOf call, we can return an undefined value
13310 // of its return type.
13311 if (fn_entry != nullptr && get_scope_typeof(scope) != nullptr &&
13312 fn_proto_node->data.fn_proto.is_extern) {
13313
13314 assert(fn_entry->body_node == nullptr);
13315 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
13316 ZigType *return_type = ir_analyze_type_expr(ira, scope, return_type_node);
13317 if (type_is_invalid(return_type))
13318 return ira->codegen->invalid_inst_gen;
13319
13320 return ir_const_undef(ira, scope, source_node, return_type);
13321 }
13322
13323 // No special handling is needed for compile time evaluation of generic functions.
13324 if (!fn_entry || fn_entry->body_node == nullptr) {
13325 ir_add_error(ira, fn_ref, buf_sprintf("unable to evaluate constant expression"));
13326 return ira->codegen->invalid_inst_gen;
13327 }
13328
13329 if (!ir_emit_backward_branch(ira, source_node))
13330 return ira->codegen->invalid_inst_gen;
13331
13332 // Fork a scope of the function with known values for the parameters.
13333 Scope *exec_scope = &fn_entry->fndef_scope->base;
13334
13335 size_t next_proto_i = 0;
13336 if (first_arg_ptr) {
13337 assert(first_arg_ptr->value->type->id == ZigTypeIdPointer);
13338
13339 bool first_arg_known_bare = false;
13340 if (fn_type_id->next_param_index >= 1) {
13341 ZigType *param_type = fn_type_id->param_info[next_proto_i].type;
13342 if (type_is_invalid(param_type))
13343 return ira->codegen->invalid_inst_gen;
13344 first_arg_known_bare = param_type->id != ZigTypeIdPointer;
13345 }
13346
13347 Stage1AirInst *first_arg;
13348 if (!first_arg_known_bare) {
13349 first_arg = first_arg_ptr;
13350 } else {
13351 first_arg = ir_get_deref(ira, first_arg_ptr->scope, first_arg_ptr->source_node, first_arg_ptr, nullptr);
13352 if (type_is_invalid(first_arg->value->type))
13353 return ira->codegen->invalid_inst_gen;
13354 }
13355
13356 if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, first_arg, &exec_scope, &next_proto_i))
13357 return ira->codegen->invalid_inst_gen;
13358 }
13359
13360 for (size_t call_i = 0; call_i < args_len; call_i += 1) {
13361 Stage1AirInst *old_arg = args_ptr[call_i];
13362
13363 if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, old_arg, &exec_scope, &next_proto_i))
13364 return ira->codegen->invalid_inst_gen;
13365 }
13366
13367 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
13368 if (return_type_node == nullptr) {
13369 ir_add_error(ira, fn_ref,
13370 buf_sprintf("TODO implement inferred return types https://github.com/ziglang/zig/issues/447"));
13371 return ira->codegen->invalid_inst_gen;
13372 }
13373 ZigType *specified_return_type = ir_analyze_type_expr(ira, exec_scope, return_type_node);
13374 if (type_is_invalid(specified_return_type))
13375 return ira->codegen->invalid_inst_gen;
13376 ZigType *return_type;
13377 ZigType *inferred_err_set_type = nullptr;
13378 if (fn_proto_node->data.fn_proto.auto_err_set) {
13379 inferred_err_set_type = get_auto_err_set_type(ira->codegen, fn_entry);
13380 if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusSizeKnown)))
13381 return ira->codegen->invalid_inst_gen;
13382 return_type = get_error_union_type(ira->codegen, inferred_err_set_type, specified_return_type);
13383 } else {
13384 return_type = specified_return_type;
13385 }
13386
13387 bool cacheable = fn_eval_cacheable(exec_scope, return_type);
13388 ZigValue *result = nullptr;
13389 if (cacheable) {
13390 // We are about to put ZigValues into a hash map. The hash of a lazy value and a
13391 // fully resolved value must equal, and so we must resolve the lazy values here.
13392 // The hash function asserts that none of the values are lazy.
13393 {
13394 Scope *scope = exec_scope;
13395 while (scope) {
13396 if (scope->id == ScopeIdVarDecl) {
13397 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
13398 if ((err = ir_resolve_lazy_recurse(
13399 var_scope->var->decl_node,
13400 var_scope->var->const_value)))
13401 {
13402 return ira->codegen->invalid_inst_gen;
13403 }
13404 } else if (scope->id == ScopeIdFnDef) {
13405 break;
13406 } else {
13407 zig_unreachable();
13408 }
13409 scope = scope->parent;
13410 }
13411 }
13412
13413 auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope);
13414 if (entry)
13415 result = entry->value;
13416 }
13417
13418 if (result == nullptr) {
13419 // Analyze the fn body block like any other constant expression.
13420 AstNode *body_node = fn_entry->body_node;
13421 ZigValue *result_ptr;
13422 create_result_ptr(ira->codegen, return_type, &result, &result_ptr);
13423
13424 if ((err = ir_eval_const_value(ira->codegen, exec_scope, body_node, result_ptr,
13425 ira->backward_branch_count, ira->backward_branch_quota,
13426 fn_entry, nullptr, source_node, nullptr, ira->new_irb.exec, return_type_node,
13427 UndefOk)))
13428 {
13429 return ira->codegen->invalid_inst_gen;
13430 }
13431
13432 if (inferred_err_set_type != nullptr) {
13433 inferred_err_set_type->data.error_set.incomplete = false;
13434 if (result->type->id == ZigTypeIdErrorUnion) {
13435 ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set;
13436 if (err != nullptr) {
13437 inferred_err_set_type->data.error_set.err_count = 1;
13438 inferred_err_set_type->data.error_set.errors = heap::c_allocator.create<ErrorTableEntry *>();
13439 inferred_err_set_type->data.error_set.errors[0] = err;
13440 }
13441 ZigType *fn_inferred_err_set_type = result->type->data.error_union.err_set_type;
13442 inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count;
13443 inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors;
13444 } else if (result->type->id == ZigTypeIdErrorSet) {
13445 inferred_err_set_type->data.error_set.err_count = result->type->data.error_set.err_count;
13446 inferred_err_set_type->data.error_set.errors = result->type->data.error_set.errors;
13447 }
13448 }
13449
13450 if (cacheable) {
13451 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);
13452 }
13453
13454 if (type_is_invalid(result->type)) {
13455 return ira->codegen->invalid_inst_gen;
13456 }
13457 }
13458
13459 Stage1AirInst *new_instruction = ir_const_move(ira, scope, source_node, result);
13460 return ir_finish_anal(ira, new_instruction);
13461 }
13462
13463 if (fn_type->data.fn.is_generic) {
13464 if (!fn_entry) {
13465 ir_add_error(ira, fn_ref,
13466 buf_sprintf("calling a generic function requires compile-time known function value"));
13467 return ira->codegen->invalid_inst_gen;
13468 }
13469
13470 size_t new_fn_arg_count = first_arg_1_or_0 + args_len;
13471
13472 Stage1AirInst **casted_args = heap::c_allocator.allocate<Stage1AirInst *>(new_fn_arg_count);
13473
13474 // Fork a scope of the function with known values for the parameters.
13475 Scope *parent_scope = fn_entry->fndef_scope->base.parent;
13476 ZigFn *impl_fn = create_fn(ira->codegen, fn_proto_node);
13477 impl_fn->param_source_nodes = heap::c_allocator.allocate<AstNode *>(new_fn_arg_count);
13478 buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name);
13479 impl_fn->fndef_scope = create_fndef_scope(ira->codegen, impl_fn->body_node, parent_scope, impl_fn);
13480 impl_fn->child_scope = &impl_fn->fndef_scope->base;
13481 FnTypeId inst_fn_type_id = {0};
13482 init_fn_type_id(&inst_fn_type_id, fn_proto_node, fn_type_id->cc, new_fn_arg_count);
13483 inst_fn_type_id.param_count = 0;
13484 inst_fn_type_id.is_var_args = false;
13485
13486 // TODO maybe GenericFnTypeId can be replaced with using the child_scope directly
13487 // as the key in generic_table
13488 GenericFnTypeId *generic_id = heap::c_allocator.create<GenericFnTypeId>();
13489 generic_id->fn_entry = fn_entry;
13490 generic_id->param_count = 0;
13491 generic_id->params = ira->codegen->pass1_arena->allocate<ZigValue>(new_fn_arg_count);
13492 size_t next_proto_i = 0;
13493
13494 if (first_arg_ptr) {
13495 assert(first_arg_ptr->value->type->id == ZigTypeIdPointer);
13496
13497 bool first_arg_known_bare = false;
13498 if (fn_type_id->next_param_index >= 1) {
13499 ZigType *param_type = fn_type_id->param_info[next_proto_i].type;
13500 if (type_is_invalid(param_type))
13501 return ira->codegen->invalid_inst_gen;
13502 first_arg_known_bare = param_type->id != ZigTypeIdPointer;
13503 }
13504
13505 Stage1AirInst *first_arg;
13506 if (!first_arg_known_bare) {
13507 first_arg = first_arg_ptr;
13508 } else {
13509 first_arg = ir_get_deref(ira, first_arg_ptr->scope, first_arg_ptr->source_node,
13510 first_arg_ptr, nullptr);
13511 if (type_is_invalid(first_arg->value->type))
13512 return ira->codegen->invalid_inst_gen;
13513 }
13514
13515 if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, first_arg, first_arg_ptr_src,
13516 &impl_fn->child_scope, &next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn))
13517 {
13518 return ira->codegen->invalid_inst_gen;
13519 }
13520 }
13521
13522 ZigFn *parent_fn_entry = ira->fn;
13523 assert(parent_fn_entry);
13524 for (size_t call_i = 0; call_i < args_len; call_i += 1) {
13525 Stage1AirInst *arg = args_ptr[call_i];
13526
13527 AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(next_proto_i);
13528 assert(param_decl_node->type == NodeTypeParamDecl);
13529
13530 if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, arg, arg->source_node,
13531 &impl_fn->child_scope,
13532 &next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn))
13533 {
13534 return ira->codegen->invalid_inst_gen;
13535 }
13536 }
13537
13538 if (fn_proto_node->data.fn_proto.align_expr != nullptr) {
13539 ZigValue *align_result;
13540 ZigValue *result_ptr;
13541 create_result_ptr(ira->codegen, get_align_amt_type(ira->codegen), &align_result, &result_ptr);
13542 if ((err = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
13543 fn_proto_node->data.fn_proto.align_expr, result_ptr,
13544 ira->backward_branch_count, ira->backward_branch_quota,
13545 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec,
13546 nullptr, UndefBad)))
13547 {
13548 return ira->codegen->invalid_inst_gen;
13549 }
13550 Stage1AirInstConst *const_instruction = ir_create_inst_noval<Stage1AirInstConst>(&ira->new_irb,
13551 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
13552 const_instruction->base.value = align_result;
13553
13554 uint32_t align_bytes = 0;
13555 ir_resolve_align(ira, &const_instruction->base, nullptr, &align_bytes);
13556 impl_fn->align_bytes = align_bytes;
13557 inst_fn_type_id.alignment = align_bytes;
13558 }
13559
13560 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
13561 ZigType *specified_return_type = ir_analyze_type_expr(ira, impl_fn->child_scope, return_type_node);
13562 if (type_is_invalid(specified_return_type))
13563 return ira->codegen->invalid_inst_gen;
13564
13565 if(!is_valid_return_type(specified_return_type)){
13566 ErrorMsg *msg = ir_add_error_node(ira, source_node,
13567 buf_sprintf("call to generic function with %s return type '%s' not allowed", type_id_name(specified_return_type->id), buf_ptr(&specified_return_type->name)));
13568 add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("function declared here"));
13569
13570 Tld *tld = find_decl(ira->codegen, &fn_entry->fndef_scope->base, &specified_return_type->name);
13571 if (tld != nullptr) {
13572 add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("type declared here"));
13573 }
13574 return ira->codegen->invalid_inst_gen;
13575 }
13576
13577 if (fn_proto_node->data.fn_proto.auto_err_set) {
13578 ZigType *inferred_err_set_type = get_auto_err_set_type(ira->codegen, impl_fn);
13579 if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusSizeKnown)))
13580 return ira->codegen->invalid_inst_gen;
13581 inst_fn_type_id.return_type = get_error_union_type(ira->codegen, inferred_err_set_type, specified_return_type);
13582 } else {
13583 inst_fn_type_id.return_type = specified_return_type;
13584 }
13585
13586 switch (type_requires_comptime(ira->codegen, specified_return_type)) {
13587 case ReqCompTimeYes:
13588 // Throw out our work and call the function as if it were comptime.
13589 return ir_analyze_fn_call(ira, scope, source_node, fn_entry, fn_type, fn_ref, first_arg_ptr,
13590 first_arg_ptr_src, CallModifierCompileTime, new_stack, new_stack_src, is_async_call_builtin,
13591 args_ptr, args_len, ret_ptr, call_result_loc);
13592 case ReqCompTimeInvalid:
13593 return ira->codegen->invalid_inst_gen;
13594 case ReqCompTimeNo:
13595 break;
13596 }
13597
13598 // We are about to put ZigValues into a hash map. The hash of a lazy value and a
13599 // fully resolved value must equal, and so we must resolve the lazy values here.
13600 // The hash function asserts that none of the values are lazy.
13601 for (size_t i = 0; i < generic_id->param_count; i += 1) {
13602 ZigValue *generic_param = &generic_id->params[i];
13603 if (generic_param->special != ConstValSpecialRuntime) {
13604 if ((err = ir_resolve_lazy_recurse(source_node, generic_param))) {
13605 return ira->codegen->invalid_inst_gen;
13606 }
13607 }
13608 }
13609
13610 auto existing_entry = ira->codegen->generic_table.put_unique(generic_id, impl_fn);
13611 if (existing_entry) {
13612 // throw away all our work and use the existing function
13613 impl_fn = existing_entry->value;
13614 } else {
13615 // finish instantiating the function
13616 impl_fn->type_entry = get_fn_type(ira->codegen, &inst_fn_type_id);
13617 if (type_is_invalid(impl_fn->type_entry))
13618 return ira->codegen->invalid_inst_gen;
13619
13620 impl_fn->analyzed_executable.source_node = source_node;
13621 impl_fn->analyzed_executable.parent_exec = ira->new_irb.exec;
13622 impl_fn->branch_quota = *ira->backward_branch_quota;
13623
13624 ira->codegen->fn_defs.append(impl_fn);
13625 }
13626
13627 FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;
13628
13629 if (fn_type_can_fail(impl_fn_type_id)) {
13630 parent_fn_entry->calls_or_awaits_errorable_fn = true;
13631 }
13632
13633 Stage1AirInst *casted_new_stack = analyze_casted_new_stack(ira, scope, source_node, new_stack,
13634 new_stack_src, is_async_call_builtin, impl_fn);
13635 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))
13636 return ira->codegen->invalid_inst_gen;
13637
13638 size_t impl_param_count = impl_fn_type_id->param_count;
13639 if (modifier == CallModifierAsync) {
13640 Stage1AirInst *result = ir_analyze_async_call(ira, scope, source_node, impl_fn, impl_fn->type_entry,
13641 nullptr, casted_args, impl_param_count, casted_new_stack, is_async_call_builtin, ret_ptr,
13642 call_result_loc);
13643 return ir_finish_anal(ira, result);
13644 }
13645
13646 Stage1AirInst *result_loc;
13647 if (handle_is_ptr(ira->codegen, impl_fn_type_id->return_type)) {
13648 result_loc = ir_resolve_result(ira, ira->suspend_source_instr, call_result_loc,
13649 impl_fn_type_id->return_type, nullptr, true, false);
13650 if (result_loc != nullptr) {
13651 if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
13652 return result_loc;
13653 }
13654 if (result_loc->value->type->data.pointer.is_const) {
13655 ir_add_error_node(ira, source_node, buf_sprintf("cannot assign to constant"));
13656 return ira->codegen->invalid_inst_gen;
13657 }
13658
13659 Stage1AirInst *dummy_value = ir_const(ira, scope, source_node, impl_fn_type_id->return_type);
13660 dummy_value->value->special = ConstValSpecialRuntime;
13661 Stage1AirInst *dummy_result = ir_implicit_cast2(ira, scope, source_node,
13662 dummy_value, result_loc->value->type->data.pointer.child_type);
13663 if (type_is_invalid(dummy_result->value->type))
13664 return ira->codegen->invalid_inst_gen;
13665 ZigType *res_child_type = result_loc->value->type->data.pointer.child_type;
13666 if (res_child_type == ira->codegen->builtin_types.entry_anytype) {
13667 res_child_type = impl_fn_type_id->return_type;
13668 }
13669 if (!handle_is_ptr(ira->codegen, res_child_type)) {
13670 ir_reset_result(call_result_loc);
13671 result_loc = nullptr;
13672 }
13673 }
13674 } else if (is_async_call_builtin) {
13675 result_loc = get_async_call_result_loc(ira, scope, source_node, impl_fn_type_id->return_type,
13676 is_async_call_builtin, args_ptr, args_len, ret_ptr);
13677 if (result_loc != nullptr && type_is_invalid(result_loc->value->type))
13678 return ira->codegen->invalid_inst_gen;
13679 } else {
13680 result_loc = nullptr;
13681 }
13682
13683 if (impl_fn_type_id->cc == CallingConventionAsync &&
13684 parent_fn_entry->inferred_async_node == nullptr &&
13685 modifier != CallModifierNoSuspend)
13686 {
13687 parent_fn_entry->inferred_async_node = fn_ref->source_node;
13688 parent_fn_entry->inferred_async_fn = impl_fn;
13689 }
13690
13691 Stage1AirInstCall *new_call_instruction = ir_build_call_gen(ira, scope, source_node,
13692 impl_fn, nullptr, impl_param_count, casted_args, modifier, casted_new_stack,
13693 is_async_call_builtin, result_loc, impl_fn_type_id->return_type);
13694
13695 if (get_scope_typeof(scope) == nullptr) {
13696 parent_fn_entry->call_list.append(new_call_instruction);
13697 }
13698
13699 return ir_finish_anal(ira, &new_call_instruction->base);
13700 }
13701
13702 ZigFn *parent_fn_entry = ira->fn;
13703 assert(fn_type_id->return_type != nullptr);
13704 assert(parent_fn_entry != nullptr);
13705 if (fn_type_can_fail(fn_type_id)) {
13706 parent_fn_entry->calls_or_awaits_errorable_fn = true;
13707 }
13708
13709
13710 Stage1AirInst **casted_args = heap::c_allocator.allocate<Stage1AirInst *>(call_param_count);
13711 size_t next_arg_index = 0;
13712 if (first_arg_ptr) {
13713 assert(first_arg_ptr->value->type->id == ZigTypeIdPointer);
13714
13715 ZigType *param_type = fn_type_id->param_info[next_arg_index].type;
13716 if (type_is_invalid(param_type))
13717 return ira->codegen->invalid_inst_gen;
13718
13719 Stage1AirInst *first_arg;
13720 if (param_type->id == ZigTypeIdPointer) {
13721 first_arg = first_arg_ptr;
13722 } else {
13723 first_arg = ir_get_deref(ira, first_arg_ptr->scope, first_arg_ptr->source_node,
13724 first_arg_ptr, nullptr);
13725 if (type_is_invalid(first_arg->value->type))
13726 return ira->codegen->invalid_inst_gen;
13727 }
13728
13729 Stage1AirInst *casted_arg = ir_implicit_cast2(ira, first_arg->scope, first_arg_ptr_src, first_arg, param_type);
13730 if (type_is_invalid(casted_arg->value->type))
13731 return ira->codegen->invalid_inst_gen;
13732
13733 casted_args[next_arg_index] = casted_arg;
13734 next_arg_index += 1;
13735 }
13736 for (size_t call_i = 0; call_i < args_len; call_i += 1) {
13737 Stage1AirInst *old_arg = args_ptr[call_i];
13738 if (type_is_invalid(old_arg->value->type))
13739 return ira->codegen->invalid_inst_gen;
13740
13741 Stage1AirInst *casted_arg;
13742 if (next_arg_index < src_param_count) {
13743 ZigType *param_type = fn_type_id->param_info[next_arg_index].type;
13744 if (type_is_invalid(param_type))
13745 return ira->codegen->invalid_inst_gen;
13746 casted_arg = ir_implicit_cast(ira, old_arg, param_type);
13747 if (type_is_invalid(casted_arg->value->type))
13748 return ira->codegen->invalid_inst_gen;
13749 } else {
13750 casted_arg = old_arg;
13751 }
13752
13753 casted_args[next_arg_index] = casted_arg;
13754 next_arg_index += 1;
13755 }
13756
13757 assert(next_arg_index == call_param_count);
13758
13759 ZigType *return_type = fn_type_id->return_type;
13760 if (type_is_invalid(return_type))
13761 return ira->codegen->invalid_inst_gen;
13762
13763 if (fn_entry != nullptr && fn_type_id->cc == CallingConventionInline && modifier == CallModifierNeverInline) {
13764 ir_add_error_node(ira, source_node,
13765 buf_sprintf("no-inline call of inline function"));
13766 return ira->codegen->invalid_inst_gen;
13767 }
13768
13769 Stage1AirInst *casted_new_stack = analyze_casted_new_stack(ira, scope, source_node, new_stack, new_stack_src,
13770 is_async_call_builtin, fn_entry);
13771 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))
13772 return ira->codegen->invalid_inst_gen;
13773
13774 if (modifier == CallModifierAsync) {
13775 Stage1AirInst *result = ir_analyze_async_call(ira, scope, source_node, fn_entry, fn_type, fn_ref,
13776 casted_args, call_param_count, casted_new_stack, is_async_call_builtin, ret_ptr, call_result_loc);
13777 return ir_finish_anal(ira, result);
13778 }
13779
13780 if (fn_type_id->cc == CallingConventionAsync &&
13781 parent_fn_entry->inferred_async_node == nullptr &&
13782 modifier != CallModifierNoSuspend)
13783 {
13784 parent_fn_entry->inferred_async_node = fn_ref->source_node;
13785 parent_fn_entry->inferred_async_fn = fn_entry;
13786 }
13787
13788 Stage1AirInst *result_loc;
13789 if (handle_is_ptr(ira->codegen, return_type)) {
13790 result_loc = ir_resolve_result(ira, ira->suspend_source_instr, call_result_loc,
13791 return_type, nullptr, true, false);
13792 if (result_loc != nullptr) {
13793 if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
13794 return result_loc;
13795 }
13796 if (result_loc->value->type->data.pointer.is_const) {
13797 ir_add_error_node(ira, source_node, buf_sprintf("cannot assign to constant"));
13798 return ira->codegen->invalid_inst_gen;
13799 }
13800
13801 ZigType *expected_return_type = result_loc->value->type->data.pointer.child_type;
13802
13803 Stage1AirInst *dummy_value = ir_const(ira, scope, source_node, return_type);
13804 dummy_value->value->special = ConstValSpecialRuntime;
13805 Stage1AirInst *dummy_result = ir_implicit_cast2(ira, scope, source_node,
13806 dummy_value, expected_return_type);
13807 if (type_is_invalid(dummy_result->value->type)) {
13808 if ((return_type->id == ZigTypeIdErrorUnion || return_type->id == ZigTypeIdErrorSet) &&
13809 expected_return_type->id != ZigTypeIdErrorUnion && expected_return_type->id != ZigTypeIdErrorSet)
13810 {
13811 if (call_result_loc->id == ResultLocIdReturn) {
13812 add_error_note(ira->codegen, ira->new_irb.exec->first_err_trace_msg,
13813 ira->explicit_return_type_source_node, buf_sprintf("function cannot return an error"));
13814 } else {
13815 add_error_note(ira->codegen, ira->new_irb.exec->first_err_trace_msg, result_loc->source_node,
13816 buf_sprintf("cannot store an error in type '%s'", buf_ptr(&expected_return_type->name)));
13817 }
13818 }
13819 return ira->codegen->invalid_inst_gen;
13820 }
13821 if (expected_return_type == ira->codegen->builtin_types.entry_anytype) {
13822 expected_return_type = return_type;
13823 }
13824 if (!handle_is_ptr(ira->codegen, expected_return_type)) {
13825 ir_reset_result(call_result_loc);
13826 result_loc = nullptr;
13827 }
13828 }
13829 } else if (is_async_call_builtin) {
13830 result_loc = get_async_call_result_loc(ira, scope, source_node, return_type, is_async_call_builtin,
13831 args_ptr, args_len, ret_ptr);
13832 if (result_loc != nullptr && type_is_invalid(result_loc->value->type))
13833 return ira->codegen->invalid_inst_gen;
13834 } else {
13835 result_loc = nullptr;
13836 }
13837
13838 Stage1AirInstCall *new_call_instruction = ir_build_call_gen(ira, scope, source_node, fn_entry, fn_ref,
13839 call_param_count, casted_args, modifier, casted_new_stack,
13840 is_async_call_builtin, result_loc, return_type);
13841 if (get_scope_typeof(scope) == nullptr) {
13842 parent_fn_entry->call_list.append(new_call_instruction);
13843 }
13844 return ir_finish_anal(ira, &new_call_instruction->base);
13845}
13846
13847static Stage1AirInst *ir_analyze_fn_call_src(IrAnalyze *ira, Stage1ZirInstCall *call_instruction,
13848 ZigFn *fn_entry, ZigType *fn_type, Stage1AirInst *fn_ref,
13849 Stage1AirInst *first_arg_ptr, AstNode *first_arg_ptr_src, CallModifier modifier)
13850{
13851 Stage1AirInst *new_stack = nullptr;
13852 AstNode *new_stack_src = nullptr;
13853 if (call_instruction->new_stack) {
13854 new_stack = call_instruction->new_stack->child;
13855 if (type_is_invalid(new_stack->value->type))
13856 return ira->codegen->invalid_inst_gen;
13857 new_stack_src = call_instruction->new_stack->source_node;
13858 }
13859 Stage1AirInst **args_ptr = heap::c_allocator.allocate<Stage1AirInst *>(call_instruction->arg_count);
13860 for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
13861 args_ptr[i] = call_instruction->args[i]->child;
13862 if (type_is_invalid(args_ptr[i]->value->type))
13863 return ira->codegen->invalid_inst_gen;
13864 }
13865 Stage1AirInst *ret_ptr = nullptr;
13866 if (call_instruction->ret_ptr != nullptr) {
13867 ret_ptr = call_instruction->ret_ptr->child;
13868 if (type_is_invalid(ret_ptr->value->type))
13869 return ira->codegen->invalid_inst_gen;
13870 }
13871 Stage1AirInst *result = ir_analyze_fn_call(ira, call_instruction->base.scope,
13872 call_instruction->base.source_node, fn_entry, fn_type, fn_ref,
13873 first_arg_ptr, first_arg_ptr_src, modifier, new_stack, new_stack_src,
13874 call_instruction->is_async_call_builtin, args_ptr, call_instruction->arg_count, ret_ptr,
13875 call_instruction->result_loc);
13876 heap::c_allocator.deallocate(args_ptr, call_instruction->arg_count);
13877 return result;
13878}
13879
13880static Stage1AirInst *ir_analyze_call_extra(IrAnalyze *ira, Scope *scope, AstNode *source_node,
13881 Stage1ZirInst *pass1_options, Stage1ZirInst *pass1_fn_ref, Stage1AirInst **args_ptr, size_t args_len,
13882 ResultLoc *result_loc)
13883{
13884 Stage1AirInst *options = pass1_options->child;
13885 if (type_is_invalid(options->value->type))
13886 return ira->codegen->invalid_inst_gen;
13887
13888 Stage1AirInst *fn_ref = pass1_fn_ref->child;
13889 if (type_is_invalid(fn_ref->value->type))
13890 return ira->codegen->invalid_inst_gen;
13891
13892 TypeStructField *modifier_field = find_struct_type_field(options->value->type, buf_create_from_str("modifier"));
13893 src_assert(modifier_field != nullptr, source_node);
13894 Stage1AirInst *modifier_inst = ir_analyze_struct_value_field_value(ira, scope, source_node, options, modifier_field);
13895 ZigValue *modifier_val = ir_resolve_const(ira, modifier_inst, UndefBad);
13896 if (modifier_val == nullptr)
13897 return ira->codegen->invalid_inst_gen;
13898 CallModifier modifier = (CallModifier)bigint_as_u32(&modifier_val->data.x_enum_tag);
13899
13900 if (ir_should_inline(ira->zir, scope)) {
13901 switch (modifier) {
13902 case CallModifierBuiltin:
13903 zig_unreachable();
13904 case CallModifierAsync:
13905 ir_add_error_node(ira, source_node, buf_sprintf("TODO: comptime @call with async modifier"));
13906 return ira->codegen->invalid_inst_gen;
13907 case CallModifierCompileTime:
13908 case CallModifierNone:
13909 case CallModifierAlwaysInline:
13910 case CallModifierAlwaysTail:
13911 case CallModifierNoSuspend:
13912 modifier = CallModifierCompileTime;
13913 break;
13914 case CallModifierNeverInline:
13915 ir_add_error_node(ira, source_node,
13916 buf_sprintf("unable to perform 'never_inline' call at compile-time"));
13917 return ira->codegen->invalid_inst_gen;
13918 case CallModifierNeverTail:
13919 ir_add_error_node(ira, source_node,
13920 buf_sprintf("unable to perform 'never_tail' call at compile-time"));
13921 return ira->codegen->invalid_inst_gen;
13922 }
13923 }
13924
13925 Stage1AirInst *first_arg_ptr = nullptr;
13926 AstNode *first_arg_ptr_src = nullptr;
13927 ZigFn *fn = nullptr;
13928 if (instr_is_comptime(fn_ref)) {
13929 if (fn_ref->value->type->id == ZigTypeIdBoundFn) {
13930 assert(fn_ref->value->special == ConstValSpecialStatic);
13931 fn = fn_ref->value->data.x_bound_fn.fn;
13932 first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg;
13933 first_arg_ptr_src = fn_ref->value->data.x_bound_fn.first_arg_src;
13934 if (type_is_invalid(first_arg_ptr->value->type))
13935 return ira->codegen->invalid_inst_gen;
13936 } else {
13937 fn = ir_resolve_fn(ira, fn_ref);
13938 }
13939 }
13940
13941 // Some modifiers require the callee to be comptime-known
13942 switch (modifier) {
13943 case CallModifierCompileTime:
13944 case CallModifierAlwaysInline:
13945 case CallModifierAsync:
13946 if (fn == nullptr) {
13947 ir_add_error(ira, modifier_inst,
13948 buf_sprintf("the specified modifier requires a comptime-known function"));
13949 return ira->codegen->invalid_inst_gen;
13950 }
13951 ZIG_FALLTHROUGH;
13952 default:
13953 break;
13954 }
13955
13956 ZigType *fn_type = (fn != nullptr) ? fn->type_entry : fn_ref->value->type;
13957
13958 TypeStructField *stack_field = find_struct_type_field(options->value->type, buf_create_from_str("stack"));
13959 src_assert(stack_field != nullptr, source_node);
13960 Stage1AirInst *opt_stack = ir_analyze_struct_value_field_value(ira, scope, source_node, options, stack_field);
13961 if (type_is_invalid(opt_stack->value->type))
13962 return ira->codegen->invalid_inst_gen;
13963
13964 Stage1AirInst *stack_is_non_null_inst = ir_analyze_test_non_null(ira, scope, source_node, opt_stack);
13965 bool stack_is_non_null;
13966 if (!ir_resolve_bool(ira, stack_is_non_null_inst, &stack_is_non_null))
13967 return ira->codegen->invalid_inst_gen;
13968
13969 Stage1AirInst *stack = nullptr;
13970 AstNode *stack_src = nullptr;
13971 if (stack_is_non_null) {
13972 stack = ir_analyze_optional_value_payload_value(ira, scope, source_node, opt_stack, false);
13973 if (type_is_invalid(stack->value->type))
13974 return ira->codegen->invalid_inst_gen;
13975 stack_src = stack->source_node;
13976 }
13977
13978 return ir_analyze_fn_call(ira, scope, source_node, fn, fn_type, fn_ref, first_arg_ptr, first_arg_ptr_src,
13979 modifier, stack, stack_src, false, args_ptr, args_len, nullptr, result_loc);
13980}
13981
13982static Stage1AirInst *ir_analyze_async_call_extra(IrAnalyze *ira, Scope *scope, AstNode *source_node, CallModifier modifier,
13983 Stage1ZirInst *pass1_fn_ref, Stage1ZirInst *ret_ptr, Stage1ZirInst *new_stack, Stage1AirInst **args_ptr, size_t args_len, ResultLoc *result_loc)
13984{
13985 Stage1AirInst *fn_ref = pass1_fn_ref->child;
13986 if (type_is_invalid(fn_ref->value->type))
13987 return ira->codegen->invalid_inst_gen;
13988
13989 if (ir_should_inline(ira->zir, scope)) {
13990 ir_add_error_node(ira, source_node, buf_sprintf("TODO: comptime @asyncCall"));
13991 return ira->codegen->invalid_inst_gen;
13992 }
13993
13994 Stage1AirInst *first_arg_ptr = nullptr;
13995 AstNode *first_arg_ptr_src = nullptr;
13996 ZigFn *fn = nullptr;
13997 if (instr_is_comptime(fn_ref)) {
13998 if (fn_ref->value->type->id == ZigTypeIdBoundFn) {
13999 assert(fn_ref->value->special == ConstValSpecialStatic);
14000 fn = fn_ref->value->data.x_bound_fn.fn;
14001 first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg;
14002 first_arg_ptr_src = fn_ref->value->data.x_bound_fn.first_arg_src;
14003 if (type_is_invalid(first_arg_ptr->value->type))
14004 return ira->codegen->invalid_inst_gen;
14005 } else {
14006 fn = ir_resolve_fn(ira, fn_ref);
14007 }
14008 }
14009
14010 Stage1AirInst *ret_ptr_uncasted = nullptr;
14011 if (ret_ptr != nullptr) {
14012 ret_ptr_uncasted = ret_ptr->child;
14013 if (type_is_invalid(ret_ptr_uncasted->value->type))
14014 return ira->codegen->invalid_inst_gen;
14015 }
14016
14017 ZigType *fn_type = (fn != nullptr) ? fn->type_entry : fn_ref->value->type;
14018 Stage1AirInst *casted_new_stack = analyze_casted_new_stack(ira, scope, source_node,
14019 new_stack->child, new_stack->source_node, true, fn);
14020 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))
14021 return ira->codegen->invalid_inst_gen;
14022
14023 return ir_analyze_fn_call(ira, scope, source_node, fn, fn_type, fn_ref, first_arg_ptr,
14024 first_arg_ptr_src, modifier, casted_new_stack, new_stack->source_node, true, args_ptr,
14025 args_len, ret_ptr_uncasted, result_loc);
14026}
14027
14028static bool ir_extract_tuple_call_args(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *args, Stage1AirInst ***args_ptr, size_t *args_len) {
14029 ZigType *args_type = args->value->type;
14030 if (type_is_invalid(args_type))
14031 return false;
14032
14033 if (args_type->id != ZigTypeIdStruct) {
14034 ir_add_error(ira, args,
14035 buf_sprintf("expected tuple or struct, found '%s'", buf_ptr(&args_type->name)));
14036 return false;
14037 }
14038
14039 if (is_tuple(args_type)) {
14040 *args_len = args_type->data.structure.src_field_count;
14041 *args_ptr = heap::c_allocator.allocate<Stage1AirInst *>(*args_len);
14042 for (size_t i = 0; i < *args_len; i += 1) {
14043 TypeStructField *arg_field = args_type->data.structure.fields[i];
14044 (*args_ptr)[i] = ir_analyze_struct_value_field_value(ira, scope, source_node, args, arg_field);
14045 if (type_is_invalid((*args_ptr)[i]->value->type))
14046 return false;
14047 }
14048 } else {
14049 ir_add_error(ira, args, buf_sprintf("TODO: struct args"));
14050 return false;
14051 }
14052 return true;
14053}
14054
14055static Stage1AirInst *ir_analyze_instruction_call_extra(IrAnalyze *ira, Stage1ZirInstCallExtra *instruction) {
14056 Stage1AirInst *args = instruction->args->child;
14057 Stage1AirInst **args_ptr = nullptr;
14058 size_t args_len = 0;
14059 if (!ir_extract_tuple_call_args(ira, instruction->base.scope, instruction->base.source_node, args, &args_ptr, &args_len)) {
14060 return ira->codegen->invalid_inst_gen;
14061 }
14062
14063 Stage1AirInst *result = ir_analyze_call_extra(ira, instruction->base.scope, instruction->base.source_node, instruction->options,
14064 instruction->fn_ref, args_ptr, args_len, instruction->result_loc);
14065 heap::c_allocator.deallocate(args_ptr, args_len);
14066 return result;
14067}
14068
14069static Stage1AirInst *ir_analyze_instruction_async_call_extra(IrAnalyze *ira, Stage1ZirInstAsyncCallExtra *instruction) {
14070 Stage1AirInst *args = instruction->args->child;
14071 Stage1AirInst **args_ptr = nullptr;
14072 size_t args_len = 0;
14073 if (!ir_extract_tuple_call_args(ira, instruction->base.scope, instruction->base.source_node, args, &args_ptr, &args_len)) {
14074 return ira->codegen->invalid_inst_gen;
14075 }
14076
14077 Stage1AirInst *result = ir_analyze_async_call_extra(ira, instruction->base.scope, instruction->base.source_node, instruction->modifier,
14078 instruction->fn_ref, instruction->ret_ptr, instruction->new_stack, args_ptr, args_len, instruction->result_loc);
14079 heap::c_allocator.deallocate(args_ptr, args_len);
14080 return result;
14081}
14082
14083static Stage1AirInst *ir_analyze_instruction_call_args(IrAnalyze *ira, Stage1ZirInstCallArgs *instruction) {
14084 Stage1AirInst **args_ptr = heap::c_allocator.allocate<Stage1AirInst *>(instruction->args_len);
14085 for (size_t i = 0; i < instruction->args_len; i += 1) {
14086 args_ptr[i] = instruction->args_ptr[i]->child;
14087 if (type_is_invalid(args_ptr[i]->value->type))
14088 return ira->codegen->invalid_inst_gen;
14089 }
14090
14091 Stage1AirInst *result = ir_analyze_call_extra(ira, instruction->base.scope, instruction->base.source_node, instruction->options,
14092 instruction->fn_ref, args_ptr, instruction->args_len, instruction->result_loc);
14093 heap::c_allocator.deallocate(args_ptr, instruction->args_len);
14094 return result;
14095}
14096
14097static Stage1AirInst *ir_analyze_instruction_call(IrAnalyze *ira, Stage1ZirInstCall *call_instruction) {
14098 Stage1AirInst *fn_ref = call_instruction->fn_ref->child;
14099 if (type_is_invalid(fn_ref->value->type))
14100 return ira->codegen->invalid_inst_gen;
14101
14102 bool is_comptime = (call_instruction->modifier == CallModifierCompileTime) ||
14103 ir_should_inline(ira->zir, call_instruction->base.scope);
14104 CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier;
14105
14106 if (is_comptime || instr_is_comptime(fn_ref)) {
14107 if (fn_ref->value->type->id == ZigTypeIdMetaType) {
14108 ZigType *ty = ir_resolve_type(ira, fn_ref);
14109 if (ty == nullptr)
14110 return ira->codegen->invalid_inst_gen;
14111 ErrorMsg *msg = ir_add_error(ira, fn_ref,
14112 buf_sprintf("type '%s' not a function", buf_ptr(&ty->name)));
14113 add_error_note(ira->codegen, msg, call_instruction->base.source_node,
14114 buf_sprintf("use @as builtin for type coercion"));
14115 return ira->codegen->invalid_inst_gen;
14116 } else if (fn_ref->value->type->id == ZigTypeIdFn) {
14117 ZigFn *fn_table_entry = ir_resolve_fn(ira, fn_ref);
14118 ZigType *fn_type = fn_table_entry ? fn_table_entry->type_entry : fn_ref->value->type;
14119 CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier;
14120 return ir_analyze_fn_call_src(ira, call_instruction, fn_table_entry, fn_type,
14121 fn_ref, nullptr, nullptr, modifier);
14122 } else if (fn_ref->value->type->id == ZigTypeIdBoundFn) {
14123 assert(fn_ref->value->special == ConstValSpecialStatic);
14124 ZigFn *fn_table_entry = fn_ref->value->data.x_bound_fn.fn;
14125 Stage1AirInst *first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg;
14126 AstNode *first_arg_ptr_src = fn_ref->value->data.x_bound_fn.first_arg_src;
14127 CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier;
14128 return ir_analyze_fn_call_src(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry,
14129 fn_ref, first_arg_ptr, first_arg_ptr_src, modifier);
14130 } else {
14131 ir_add_error(ira, fn_ref,
14132 buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name)));
14133 return ira->codegen->invalid_inst_gen;
14134 }
14135 }
14136
14137 if (fn_ref->value->type->id == ZigTypeIdFn) {
14138 return ir_analyze_fn_call_src(ira, call_instruction, nullptr, fn_ref->value->type,
14139 fn_ref, nullptr, nullptr, modifier);
14140 } else {
14141 ir_add_error(ira, fn_ref,
14142 buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name)));
14143 return ira->codegen->invalid_inst_gen;
14144 }
14145}
14146
14147// out_val->type must be the type to read the pointer as
14148// if the type is different than the actual type then it does a comptime byte reinterpretation
14149static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
14150 ZigValue *out_val, ZigValue *ptr_val)
14151{
14152 Error err;
14153 assert(out_val->type != nullptr);
14154
14155 ZigValue *pointee = const_ptr_pointee_unchecked(codegen, ptr_val);
14156 src_assert(pointee->type != nullptr, source_node);
14157
14158 if ((err = type_resolve(codegen, pointee->type, ResolveStatusSizeKnown)))
14159 return ErrorSemanticAnalyzeFail;
14160 if ((err = type_resolve(codegen, out_val->type, ResolveStatusSizeKnown)))
14161 return ErrorSemanticAnalyzeFail;
14162
14163 size_t src_size = type_size(codegen, pointee->type);
14164 size_t dst_size = type_size(codegen, out_val->type);
14165
14166 if (dst_size <= src_size) {
14167 if (src_size == dst_size && types_have_same_zig_comptime_repr(codegen, out_val->type, pointee->type)) {
14168 copy_const_val(codegen, out_val, pointee);
14169 return ErrorNone;
14170 }
14171 Buf buf = BUF_INIT;
14172 buf_resize(&buf, src_size);
14173 buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf), pointee);
14174 if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
14175 return err;
14176 buf_deinit(&buf);
14177 return ErrorNone;
14178 }
14179
14180 switch (ptr_val->data.x_ptr.special) {
14181 case ConstPtrSpecialInvalid:
14182 zig_unreachable();
14183 case ConstPtrSpecialNull:
14184 if (dst_size == 0)
14185 return ErrorNone;
14186 opt_ir_add_error_node(ira, codegen, source_node,
14187 buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from null pointer",
14188 dst_size));
14189 return ErrorSemanticAnalyzeFail;
14190 case ConstPtrSpecialRef: {
14191 opt_ir_add_error_node(ira, codegen, source_node,
14192 buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from pointer to %s which is %" ZIG_PRI_usize " bytes",
14193 dst_size, buf_ptr(&pointee->type->name), src_size));
14194 return ErrorSemanticAnalyzeFail;
14195 }
14196 case ConstPtrSpecialSubArray: {
14197 ZigValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
14198 assert(array_val->type->id == ZigTypeIdArray);
14199 if (array_val->data.x_array.special != ConstArraySpecialNone)
14200 zig_panic("TODO: ir_read_const_ptr ConstPtrSpecialSubArray !ConstArraySpecialNone");
14201 if (dst_size > src_size) {
14202 size_t elem_index = ptr_val->data.x_ptr.data.base_array.elem_index;
14203 opt_ir_add_error_node(ira, codegen, source_node,
14204 buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from %s at index %" ZIG_PRI_usize " which is %" ZIG_PRI_usize " bytes",
14205 dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));
14206 return ErrorSemanticAnalyzeFail;
14207 }
14208 size_t elem_size = src_size;
14209 size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1);
14210 Buf buf = BUF_INIT;
14211 buf_resize(&buf, elem_count * elem_size);
14212 for (size_t i = 0; i < elem_count; i += 1) {
14213 ZigValue *elem_val = &array_val->data.x_array.data.s_none.elements[i];
14214 buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
14215 }
14216 if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
14217 return err;
14218 buf_deinit(&buf);
14219 return ErrorNone;
14220 }
14221 case ConstPtrSpecialBaseArray: {
14222 ZigValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
14223 assert(array_val->type->id == ZigTypeIdArray);
14224 if (array_val->data.x_array.special != ConstArraySpecialNone)
14225 zig_panic("TODO: ir_read_const_ptr ConstPtrSpecialBaseArray !ConstArraySpecialNone");
14226 size_t elem_size = src_size;
14227 size_t elem_index = ptr_val->data.x_ptr.data.base_array.elem_index;
14228 src_size = elem_size * (array_val->type->data.array.len - elem_index);
14229 if (dst_size > src_size) {
14230 opt_ir_add_error_node(ira, codegen, source_node,
14231 buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from %s at index %" ZIG_PRI_usize " which is %" ZIG_PRI_usize " bytes",
14232 dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));
14233 return ErrorSemanticAnalyzeFail;
14234 }
14235 size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1);
14236 Buf buf = BUF_INIT;
14237 buf_resize(&buf, elem_count * elem_size);
14238 for (size_t i = 0; i < elem_count; i += 1) {
14239 ZigValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i];
14240 buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
14241 }
14242 if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
14243 return err;
14244 buf_deinit(&buf);
14245 return ErrorNone;
14246 }
14247 case ConstPtrSpecialBaseStruct:
14248 case ConstPtrSpecialBaseErrorUnionCode:
14249 case ConstPtrSpecialBaseErrorUnionPayload:
14250 case ConstPtrSpecialBaseOptionalPayload:
14251 case ConstPtrSpecialDiscard:
14252 case ConstPtrSpecialHardCodedAddr:
14253 case ConstPtrSpecialFunction:
14254 zig_panic("TODO: ir_read_const_ptr");
14255 }
14256 zig_unreachable();
14257}
14258
14259static Stage1AirInst *ir_analyze_optional_type(IrAnalyze *ira, Stage1ZirInstUnOp *instruction) {
14260 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_type);
14261 result->value->special = ConstValSpecialLazy;
14262
14263 LazyValueOptType *lazy_opt_type = heap::c_allocator.create<LazyValueOptType>();
14264 lazy_opt_type->ira = ira; ira_ref(ira);
14265 result->value->data.x_lazy = &lazy_opt_type->base;
14266 lazy_opt_type->base.id = LazyValueIdOptType;
14267
14268 lazy_opt_type->payload_type = instruction->value->child;
14269 if (ir_resolve_type_lazy(ira, lazy_opt_type->payload_type) == nullptr)
14270 return ira->codegen->invalid_inst_gen;
14271
14272 return result;
14273}
14274
14275static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *scalar_type,
14276 ZigValue *operand_val, ZigValue *scalar_out_val, bool is_wrap_op)
14277{
14278 bool is_float = (scalar_type->id == ZigTypeIdFloat || scalar_type->id == ZigTypeIdComptimeFloat);
14279
14280 bool ok_type = scalar_type->id == ZigTypeIdInt || scalar_type->id == ZigTypeIdComptimeInt ||
14281 (is_float && !is_wrap_op);
14282
14283 if (!ok_type) {
14284 const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
14285 return ir_add_error_node(ira, source_node, buf_sprintf(fmt, buf_ptr(&scalar_type->name)));
14286 }
14287
14288 if (is_float) {
14289 float_negate(scalar_out_val, operand_val);
14290 } else if (is_wrap_op) {
14291 bigint_negate_wrap(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint,
14292 scalar_type->data.integral.bit_count, scalar_type->data.integral.is_signed);
14293 } else {
14294 bigint_negate(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint);
14295 }
14296
14297 scalar_out_val->type = scalar_type;
14298 scalar_out_val->special = ConstValSpecialStatic;
14299
14300 if (is_wrap_op || is_float || scalar_type->id == ZigTypeIdComptimeInt) {
14301 return nullptr;
14302 }
14303
14304 if (!bigint_fits_in_bits(&scalar_out_val->data.x_bigint, scalar_type->data.integral.bit_count, true)) {
14305 return ir_add_error_node(ira, source_node, buf_sprintf("negation caused overflow"));
14306 }
14307 return nullptr;
14308}
14309
14310static Stage1AirInst *ir_analyze_negation(IrAnalyze *ira, Stage1ZirInstUnOp *instruction) {
14311 Stage1AirInst *value = instruction->value->child;
14312 ZigType *expr_type = value->value->type;
14313 if (type_is_invalid(expr_type))
14314 return ira->codegen->invalid_inst_gen;
14315
14316 bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap);
14317
14318 ZigType *scalar_type = (expr_type->id == ZigTypeIdVector) ?
14319 expr_type->data.vector.elem_type : expr_type;
14320
14321 switch (scalar_type->id) {
14322 case ZigTypeIdComptimeInt:
14323 case ZigTypeIdFloat:
14324 case ZigTypeIdComptimeFloat:
14325 break;
14326 case ZigTypeIdInt:
14327 if (is_wrap_op || scalar_type->data.integral.is_signed)
14328 break;
14329 ZIG_FALLTHROUGH;
14330 default:
14331 ir_add_error_node(ira, instruction->base.source_node,
14332 buf_sprintf("negation of type '%s'", buf_ptr(&scalar_type->name)));
14333 return ira->codegen->invalid_inst_gen;
14334 }
14335
14336 if (instr_is_comptime(value)) {
14337 ZigValue *operand_val = ir_resolve_const(ira, value, UndefBad);
14338 if (!operand_val)
14339 return ira->codegen->invalid_inst_gen;
14340
14341 Stage1AirInst *result_instruction = ir_const(ira, instruction->base.scope, instruction->base.source_node, expr_type);
14342 ZigValue *out_val = result_instruction->value;
14343 if (expr_type->id == ZigTypeIdVector) {
14344 expand_undef_array(ira->codegen, operand_val);
14345 out_val->special = ConstValSpecialUndef;
14346 expand_undef_array(ira->codegen, out_val);
14347 size_t len = expr_type->data.vector.len;
14348 for (size_t i = 0; i < len; i += 1) {
14349 ZigValue *scalar_operand_val = &operand_val->data.x_array.data.s_none.elements[i];
14350 ZigValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i];
14351 assert(scalar_operand_val->type == scalar_type);
14352 assert(scalar_out_val->type == scalar_type);
14353 ErrorMsg *msg = ir_eval_negation_scalar(ira, instruction->base.scope, instruction->base.source_node, scalar_type,
14354 scalar_operand_val, scalar_out_val, is_wrap_op);
14355 if (msg != nullptr) {
14356 add_error_note(ira->codegen, msg, instruction->base.source_node,
14357 buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i));
14358 return ira->codegen->invalid_inst_gen;
14359 }
14360 }
14361 out_val->type = expr_type;
14362 out_val->special = ConstValSpecialStatic;
14363 } else {
14364 if (ir_eval_negation_scalar(ira, instruction->base.scope, instruction->base.source_node, scalar_type, operand_val, out_val,
14365 is_wrap_op) != nullptr)
14366 {
14367 return ira->codegen->invalid_inst_gen;
14368 }
14369 }
14370 return result_instruction;
14371 }
14372
14373 return ir_build_negation(ira, instruction->base.scope, instruction->base.source_node, value, expr_type, is_wrap_op);
14374}
14375
14376static Stage1AirInst *ir_analyze_bin_not(IrAnalyze *ira, Stage1ZirInstUnOp *instruction) {
14377 Stage1AirInst *value = instruction->value->child;
14378 ZigType *expr_type = value->value->type;
14379 if (type_is_invalid(expr_type))
14380 return ira->codegen->invalid_inst_gen;
14381
14382 ZigType *scalar_type = (expr_type->id == ZigTypeIdVector) ?
14383 expr_type->data.vector.elem_type : expr_type;
14384
14385 if (scalar_type->id != ZigTypeIdInt) {
14386 ir_add_error_node(ira, instruction->base.source_node,
14387 buf_sprintf("unable to perform binary not operation on type '%s'", buf_ptr(&expr_type->name)));
14388 return ira->codegen->invalid_inst_gen;
14389 }
14390
14391 if (instr_is_comptime(value)) {
14392 ZigValue *expr_val = ir_resolve_const(ira, value, UndefBad);
14393 if (expr_val == nullptr)
14394 return ira->codegen->invalid_inst_gen;
14395
14396 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, expr_type);
14397
14398 if (expr_type->id == ZigTypeIdVector) {
14399 expand_undef_array(ira->codegen, expr_val);
14400 result->value->special = ConstValSpecialUndef;
14401 expand_undef_array(ira->codegen, result->value);
14402
14403 for (size_t i = 0; i < expr_type->data.vector.len; i++) {
14404 ZigValue *src_val = &expr_val->data.x_array.data.s_none.elements[i];
14405 ZigValue *dst_val = &result->value->data.x_array.data.s_none.elements[i];
14406
14407 dst_val->type = scalar_type;
14408 dst_val->special = ConstValSpecialStatic;
14409 bigint_not(&dst_val->data.x_bigint, &src_val->data.x_bigint,
14410 scalar_type->data.integral.bit_count, scalar_type->data.integral.is_signed);
14411 }
14412 } else {
14413 bigint_not(&result->value->data.x_bigint, &expr_val->data.x_bigint,
14414 scalar_type->data.integral.bit_count, scalar_type->data.integral.is_signed);
14415 }
14416
14417 return result;
14418 }
14419
14420 return ir_build_binary_not(ira, instruction->base.scope, instruction->base.source_node, value, expr_type);
14421}
14422
14423static Stage1AirInst *ir_analyze_instruction_un_op(IrAnalyze *ira, Stage1ZirInstUnOp *instruction) {
14424 IrUnOp op_id = instruction->op_id;
14425 switch (op_id) {
14426 case IrUnOpInvalid:
14427 zig_unreachable();
14428 case IrUnOpBinNot:
14429 return ir_analyze_bin_not(ira, instruction);
14430 case IrUnOpNegation:
14431 case IrUnOpNegationWrap:
14432 return ir_analyze_negation(ira, instruction);
14433 case IrUnOpDereference: {
14434 Stage1AirInst *ptr = instruction->value->child;
14435 if (type_is_invalid(ptr->value->type))
14436 return ira->codegen->invalid_inst_gen;
14437 ZigType *ptr_type = ptr->value->type;
14438 if (ptr_type->id == ZigTypeIdPointer && ptr_type->data.pointer.ptr_len == PtrLenUnknown) {
14439 ir_add_error_node(ira, instruction->base.source_node,
14440 buf_sprintf("index syntax required for unknown-length pointer type '%s'",
14441 buf_ptr(&ptr_type->name)));
14442 return ira->codegen->invalid_inst_gen;
14443 }
14444
14445 Stage1AirInst *result = ir_get_deref(ira, instruction->base.scope,
14446 instruction->base.source_node, ptr, instruction->result_loc);
14447 if (type_is_invalid(result->value->type))
14448 return ira->codegen->invalid_inst_gen;
14449
14450 // If the result needs to be an lvalue, type check it
14451 if (instruction->lval != LValNone && result->value->type->id != ZigTypeIdPointer) {
14452 ir_add_error_node(ira, instruction->base.source_node,
14453 buf_sprintf("attempt to dereference non-pointer type '%s'", buf_ptr(&result->value->type->name)));
14454 return ira->codegen->invalid_inst_gen;
14455 }
14456
14457 return result;
14458 }
14459 case IrUnOpOptional:
14460 return ir_analyze_optional_type(ira, instruction);
14461 }
14462 zig_unreachable();
14463}
14464
14465static void ir_push_resume(IrAnalyze *ira, IrSuspendPosition pos) {
14466 Stage1ZirBasicBlock *old_bb = ira->zir->basic_block_list.at(pos.basic_block_index);
14467 if (old_bb->in_resume_stack) return;
14468 ira->resume_stack.append(pos);
14469 old_bb->in_resume_stack = true;
14470}
14471
14472static void ir_push_resume_block(IrAnalyze *ira, Stage1ZirBasicBlock *old_bb) {
14473 if (ira->resume_stack.length != 0) {
14474 ir_push_resume(ira, {old_bb->index, 0});
14475 }
14476}
14477
14478static Stage1AirInst *ir_analyze_instruction_br(IrAnalyze *ira, Stage1ZirInstBr *br_instruction) {
14479 Stage1ZirBasicBlock *old_dest_block = br_instruction->dest_block;
14480
14481 bool is_comptime;
14482 if (!ir_resolve_comptime(ira, br_instruction->is_comptime->child, &is_comptime))
14483 return ir_unreach_error(ira);
14484
14485 if (is_comptime || (old_dest_block->ref_count == 1 && old_dest_block->suspend_instruction_ref == nullptr))
14486 return ir_inline_bb(ira, br_instruction->base.source_node, old_dest_block);
14487
14488 Stage1AirBasicBlock *new_bb = ir_get_new_bb_runtime(ira, old_dest_block, &br_instruction->base);
14489 if (new_bb == nullptr)
14490 return ir_unreach_error(ira);
14491
14492 ir_push_resume_block(ira, old_dest_block);
14493
14494 Stage1AirInst *result = ir_build_br_gen(ira, br_instruction->base.scope, br_instruction->base.source_node, new_bb);
14495 return ir_finish_anal(ira, result);
14496}
14497
14498static Stage1AirInst *ir_analyze_instruction_cond_br(IrAnalyze *ira, Stage1ZirInstCondBr *cond_br_instruction) {
14499 Stage1AirInst *condition = cond_br_instruction->condition->child;
14500 if (type_is_invalid(condition->value->type))
14501 return ir_unreach_error(ira);
14502
14503 bool is_comptime;
14504 if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime))
14505 return ir_unreach_error(ira);
14506
14507 ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
14508 Stage1AirInst *casted_condition = ir_implicit_cast(ira, condition, bool_type);
14509 if (type_is_invalid(casted_condition->value->type))
14510 return ir_unreach_error(ira);
14511
14512 if (is_comptime || instr_is_comptime(casted_condition)) {
14513 bool cond_is_true;
14514 if (!ir_resolve_bool(ira, casted_condition, &cond_is_true))
14515 return ir_unreach_error(ira);
14516
14517 Stage1ZirBasicBlock *old_dest_block = cond_is_true ?
14518 cond_br_instruction->then_block : cond_br_instruction->else_block;
14519
14520 if (is_comptime || (old_dest_block->ref_count == 1 && old_dest_block->suspend_instruction_ref == nullptr))
14521 return ir_inline_bb(ira, cond_br_instruction->base.source_node, old_dest_block);
14522
14523 Stage1AirBasicBlock *new_dest_block = ir_get_new_bb_runtime(ira, old_dest_block, &cond_br_instruction->base);
14524 if (new_dest_block == nullptr)
14525 return ir_unreach_error(ira);
14526
14527 ir_push_resume_block(ira, old_dest_block);
14528
14529 Stage1AirInst *result = ir_build_br_gen(ira, cond_br_instruction->base.scope,
14530 cond_br_instruction->base.source_node, new_dest_block);
14531 return ir_finish_anal(ira, result);
14532 }
14533
14534 assert(cond_br_instruction->then_block != cond_br_instruction->else_block);
14535 Stage1AirBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base);
14536 if (new_then_block == nullptr)
14537 return ir_unreach_error(ira);
14538
14539 Stage1AirBasicBlock *new_else_block = ir_get_new_bb_runtime(ira, cond_br_instruction->else_block, &cond_br_instruction->base);
14540 if (new_else_block == nullptr)
14541 return ir_unreach_error(ira);
14542
14543 ir_push_resume_block(ira, cond_br_instruction->else_block);
14544 ir_push_resume_block(ira, cond_br_instruction->then_block);
14545
14546 Stage1AirInst *result = ir_build_cond_br_gen(ira, cond_br_instruction->base.scope,
14547 cond_br_instruction->base.source_node, casted_condition, new_then_block,
14548 new_else_block);
14549 return ir_finish_anal(ira, result);
14550}
14551
14552static Stage1AirInst *ir_analyze_instruction_unreachable(IrAnalyze *ira,
14553 Stage1ZirInstUnreachable *unreachable_instruction)
14554{
14555 if (ir_should_inline(ira->zir, unreachable_instruction->base.scope)) {
14556 ir_add_error_node(ira, unreachable_instruction->base.source_node,
14557 buf_sprintf("reached unreachable code"));
14558 return ir_unreach_error(ira);
14559 }
14560
14561 Stage1AirInst *result = ir_build_unreachable_gen(ira, unreachable_instruction->base.scope,
14562 unreachable_instruction->base.source_node);
14563 return ir_finish_anal(ira, result);
14564}
14565
14566static Stage1AirInst *ir_analyze_instruction_phi(IrAnalyze *ira, Stage1ZirInstPhi *phi_instruction) {
14567 Error err;
14568
14569 if (ira->const_predecessor_bb) {
14570 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
14571 Stage1ZirBasicBlock *predecessor = phi_instruction->incoming_blocks[i];
14572 if (predecessor != ira->const_predecessor_bb)
14573 continue;
14574 Stage1AirInst *value = phi_instruction->incoming_values[i]->child;
14575 assert(value->value->type);
14576 if (type_is_invalid(value->value->type))
14577 return ira->codegen->invalid_inst_gen;
14578
14579 if (value->value->special != ConstValSpecialRuntime) {
14580 Stage1AirInst *result = ir_const(ira, phi_instruction->base.scope,
14581 phi_instruction->base.source_node, nullptr);
14582 copy_const_val(ira->codegen, result->value, value->value);
14583 return result;
14584 } else {
14585 return value;
14586 }
14587 }
14588 zig_unreachable();
14589 }
14590
14591 ResultLocPeerParent *peer_parent = phi_instruction->peer_parent;
14592 if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming &&
14593 peer_parent->peers.length >= 2)
14594 {
14595 if (peer_parent->resolved_type == nullptr) {
14596 Stage1AirInst **instructions = heap::c_allocator.allocate<Stage1AirInst *>(peer_parent->peers.length);
14597 for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
14598 ResultLocPeer *this_peer = peer_parent->peers.at(i);
14599
14600 Stage1AirInst *gen_instruction = this_peer->base.gen_instruction;
14601 if (gen_instruction == nullptr) {
14602 // unreachable instructions will cause implicit_elem_type to be null
14603 if (this_peer->base.implicit_elem_type == nullptr) {
14604 instructions[i] = ir_const_unreachable(ira, this_peer->base.source_instruction->scope, this_peer->base.source_instruction->source_node);
14605 } else {
14606 instructions[i] = ir_const(ira, this_peer->base.source_instruction->scope,
14607 this_peer->base.source_instruction->source_node,
14608 this_peer->base.implicit_elem_type);
14609 instructions[i]->value->special = ConstValSpecialRuntime;
14610 }
14611 } else {
14612 instructions[i] = gen_instruction;
14613 }
14614
14615 }
14616 ZigType *expected_type = ir_result_loc_expected_type(ira, peer_parent->parent);
14617 peer_parent->resolved_type = ir_resolve_peer_types(ira,
14618 peer_parent->base.source_instruction->source_node, expected_type, instructions,
14619 peer_parent->peers.length);
14620 if (type_is_invalid(peer_parent->resolved_type))
14621 return ira->codegen->invalid_inst_gen;
14622
14623 // the logic below assumes there are no instructions in the new current basic block yet
14624 src_assert(ira->new_irb.current_basic_block->instruction_list.length == 0,
14625 phi_instruction->base.source_node);
14626
14627 // In case resolving the parent activates a suspend, do it now
14628 Stage1AirInst *parent_result_loc = ir_resolve_result(ira, &phi_instruction->base, peer_parent->parent,
14629 peer_parent->resolved_type, nullptr, false, true);
14630 if (parent_result_loc != nullptr &&
14631 (type_is_invalid(parent_result_loc->value->type) || parent_result_loc->value->type->id == ZigTypeIdUnreachable))
14632 {
14633 return parent_result_loc;
14634 }
14635 // If the above code generated any instructions in the current basic block, we need
14636 // to move them to the peer parent predecessor.
14637 ZigList<Stage1AirInst *> instrs_to_move = {};
14638 while (ira->new_irb.current_basic_block->instruction_list.length != 0) {
14639 instrs_to_move.append(ira->new_irb.current_basic_block->instruction_list.pop());
14640 }
14641 if (instrs_to_move.length != 0) {
14642 Stage1AirBasicBlock *predecessor = peer_parent->base.source_instruction->owner_bb->child;
14643 Stage1AirInst *branch_instruction = predecessor->instruction_list.pop();
14644 src_assert(branch_instruction->value->type->id == ZigTypeIdUnreachable,
14645 phi_instruction->base.source_node);
14646 while (instrs_to_move.length != 0) {
14647 predecessor->instruction_list.append(instrs_to_move.pop());
14648 }
14649 predecessor->instruction_list.append(branch_instruction);
14650 instrs_to_move.deinit();
14651 }
14652 }
14653
14654 IrSuspendPosition suspend_pos;
14655 ira_suspend(ira, &phi_instruction->base, nullptr, &suspend_pos);
14656 ir_push_resume(ira, suspend_pos);
14657
14658 for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
14659 ResultLocPeer *opposite_peer = peer_parent->peers.at(peer_parent->peers.length - i - 1);
14660 if (opposite_peer->base.implicit_elem_type != nullptr &&
14661 opposite_peer->base.implicit_elem_type->id != ZigTypeIdUnreachable)
14662 {
14663 ir_push_resume(ira, opposite_peer->suspend_pos);
14664 }
14665 }
14666
14667 peer_parent->done_resuming = true;
14668 return ira_resume(ira);
14669 }
14670
14671 ZigList<Stage1AirBasicBlock*> new_incoming_blocks = {0};
14672 ZigList<Stage1AirInst*> new_incoming_values = {0};
14673
14674 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
14675 Stage1ZirBasicBlock *predecessor = phi_instruction->incoming_blocks[i];
14676 if (predecessor->ref_count == 0)
14677 continue;
14678
14679
14680 Stage1ZirInst *old_value = phi_instruction->incoming_values[i];
14681 assert(old_value);
14682 Stage1AirInst *new_value = old_value->child;
14683 if (!new_value || new_value->value->type->id == ZigTypeIdUnreachable || predecessor->child == nullptr)
14684 continue;
14685
14686 if (type_is_invalid(new_value->value->type))
14687 return ira->codegen->invalid_inst_gen;
14688
14689
14690 assert(predecessor->child);
14691 new_incoming_blocks.append(predecessor->child);
14692 new_incoming_values.append(new_value);
14693 }
14694
14695 if (new_incoming_blocks.length == 0) {
14696 Stage1AirInst *result = ir_build_unreachable_gen(ira, phi_instruction->base.scope,
14697 phi_instruction->base.source_node);
14698 return ir_finish_anal(ira, result);
14699 }
14700
14701 if (new_incoming_blocks.length == 1) {
14702 Stage1AirInst *incoming_value = new_incoming_values.at(0);
14703 new_incoming_blocks.deinit();
14704 new_incoming_values.deinit();
14705 return incoming_value;
14706 }
14707
14708 ZigType *resolved_type = nullptr;
14709 if (peer_parent != nullptr) {
14710 bool peer_parent_has_type;
14711 if ((err = ir_result_has_type(ira, peer_parent->parent, &peer_parent_has_type)))
14712 return ira->codegen->invalid_inst_gen;
14713 if (peer_parent_has_type) {
14714 if (peer_parent->parent->id == ResultLocIdReturn) {
14715 resolved_type = ira->explicit_return_type;
14716 } else if (peer_parent->parent->id == ResultLocIdCast) {
14717 resolved_type = ir_resolve_type(ira, peer_parent->parent->source_instruction->child);
14718 } else if (peer_parent->parent->resolved_loc) {
14719 ZigType *resolved_loc_ptr_type = peer_parent->parent->resolved_loc->value->type;
14720 src_assert(resolved_loc_ptr_type->id == ZigTypeIdPointer,
14721 phi_instruction->base.source_node);
14722 resolved_type = resolved_loc_ptr_type->data.pointer.child_type;
14723 }
14724
14725 if (resolved_type != nullptr && type_is_invalid(resolved_type))
14726 return ira->codegen->invalid_inst_gen;
14727 }
14728 }
14729
14730 if (resolved_type == nullptr) {
14731 resolved_type = ir_resolve_peer_types(ira, phi_instruction->base.source_node, nullptr,
14732 new_incoming_values.items, new_incoming_values.length);
14733 if (type_is_invalid(resolved_type))
14734 return ira->codegen->invalid_inst_gen;
14735 }
14736
14737 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
14738 case OnePossibleValueInvalid:
14739 return ira->codegen->invalid_inst_gen;
14740 case OnePossibleValueYes:
14741 return ir_const_move(ira, phi_instruction->base.scope, phi_instruction->base.source_node,
14742 get_the_one_possible_value(ira->codegen, resolved_type));
14743 case OnePossibleValueNo:
14744 break;
14745 }
14746
14747 switch (type_requires_comptime(ira->codegen, resolved_type)) {
14748 case ReqCompTimeInvalid:
14749 return ira->codegen->invalid_inst_gen;
14750 case ReqCompTimeYes:
14751 ir_add_error_node(ira, phi_instruction->base.source_node,
14752 buf_sprintf("values of type '%s' must be comptime known", buf_ptr(&resolved_type->name)));
14753 return ira->codegen->invalid_inst_gen;
14754 case ReqCompTimeNo:
14755 break;
14756 }
14757
14758 bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer);
14759
14760 // cast all values to the resolved type. however we can't put cast instructions in front of the phi instruction.
14761 // so we go back and insert the casts as the last instruction in the corresponding predecessor blocks, and
14762 // then make sure the branch instruction is preserved.
14763 Stage1AirBasicBlock *cur_bb = ira->new_irb.current_basic_block;
14764 for (size_t i = 0; i < new_incoming_values.length; i += 1) {
14765 Stage1AirInst *new_value = new_incoming_values.at(i);
14766 Stage1AirBasicBlock *predecessor = new_incoming_blocks.at(i);
14767 src_assert(predecessor->instruction_list.length != 0, phi_instruction->base.source_node);
14768 Stage1AirInst *branch_instruction = predecessor->instruction_list.pop();
14769 ir_set_cursor_at_end_gen(&ira->new_irb, predecessor);
14770 Stage1AirInst *casted_value = ir_implicit_cast(ira, new_value, resolved_type);
14771 if (type_is_invalid(casted_value->value->type)) {
14772 return ira->codegen->invalid_inst_gen;
14773 }
14774 new_incoming_values.items[i] = casted_value;
14775 predecessor->instruction_list.append(branch_instruction);
14776
14777 if (all_stack_ptrs && (casted_value->value->special != ConstValSpecialRuntime ||
14778 casted_value->value->data.rh_ptr != RuntimeHintPtrStack))
14779 {
14780 all_stack_ptrs = false;
14781 }
14782 }
14783 ir_set_cursor_at_end_gen(&ira->new_irb, cur_bb);
14784
14785 Stage1AirInst *result = ir_build_phi_gen(ira, phi_instruction->base.scope,
14786 phi_instruction->base.source_node, phi_instruction->merge_comptime,
14787 new_incoming_blocks.length, new_incoming_blocks.items, new_incoming_values.items, resolved_type);
14788
14789 if (all_stack_ptrs) {
14790 assert(result->value->special == ConstValSpecialRuntime);
14791 result->value->data.rh_ptr = RuntimeHintPtrStack;
14792 }
14793
14794 return result;
14795}
14796
14797static Stage1AirInst *ir_analyze_instruction_var_ptr(IrAnalyze *ira, Stage1ZirInstVarPtr *instruction) {
14798 ZigVar *var = instruction->var;
14799 Stage1AirInst *result = ir_get_var_ptr(ira, instruction->base.scope, instruction->base.source_node, var);
14800 if (instruction->crossed_fndef_scope != nullptr && !instr_is_comptime(result)) {
14801 ErrorMsg *msg = ir_add_error_node(ira, instruction->base.source_node,
14802 buf_sprintf("'%s' not accessible from inner function", var->name));
14803 add_error_note(ira->codegen, msg, instruction->crossed_fndef_scope->base.source_node,
14804 buf_sprintf("crossed function definition here"));
14805 add_error_note(ira->codegen, msg, var->decl_node,
14806 buf_sprintf("declared here"));
14807 return ira->codegen->invalid_inst_gen;
14808 }
14809 return result;
14810}
14811
14812static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align) {
14813 assert(ptr_type->id == ZigTypeIdPointer);
14814 return get_pointer_to_type_extra2(g,
14815 ptr_type->data.pointer.child_type,
14816 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
14817 ptr_type->data.pointer.ptr_len,
14818 new_align,
14819 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
14820 ptr_type->data.pointer.allow_zero,
14821 ptr_type->data.pointer.vector_index,
14822 ptr_type->data.pointer.inferred_struct_field,
14823 ptr_type->data.pointer.sentinel);
14824}
14825
14826static ZigType *adjust_ptr_sentinel(CodeGen *g, ZigType *ptr_type, ZigValue *new_sentinel) {
14827 assert(ptr_type->id == ZigTypeIdPointer);
14828 return get_pointer_to_type_extra2(g,
14829 ptr_type->data.pointer.child_type,
14830 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
14831 ptr_type->data.pointer.ptr_len,
14832 ptr_type->data.pointer.explicit_alignment,
14833 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
14834 ptr_type->data.pointer.allow_zero,
14835 ptr_type->data.pointer.vector_index,
14836 ptr_type->data.pointer.inferred_struct_field,
14837 new_sentinel);
14838}
14839
14840static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) {
14841 assert(is_slice(slice_type));
14842 ZigType *ptr_type = adjust_ptr_align(g, slice_type->data.structure.fields[slice_ptr_index]->type_entry,
14843 new_align);
14844 return get_slice_type(g, ptr_type);
14845}
14846
14847static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {
14848 assert(ptr_type->id == ZigTypeIdPointer);
14849 return get_pointer_to_type_extra2(g,
14850 ptr_type->data.pointer.child_type,
14851 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
14852 ptr_len,
14853 ptr_type->data.pointer.explicit_alignment,
14854 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
14855 ptr_type->data.pointer.allow_zero,
14856 ptr_type->data.pointer.vector_index,
14857 ptr_type->data.pointer.inferred_struct_field,
14858 (ptr_len != PtrLenUnknown) ? nullptr : ptr_type->data.pointer.sentinel);
14859}
14860
14861static ZigType *adjust_ptr_allow_zero(CodeGen *g, ZigType *ptr_type, bool allow_zero) {
14862 assert(ptr_type->id == ZigTypeIdPointer);
14863 return get_pointer_to_type_extra2(g,
14864 ptr_type->data.pointer.child_type,
14865 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
14866 ptr_type->data.pointer.ptr_len,
14867 ptr_type->data.pointer.explicit_alignment,
14868 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
14869 allow_zero,
14870 ptr_type->data.pointer.vector_index,
14871 ptr_type->data.pointer.inferred_struct_field,
14872 ptr_type->data.pointer.sentinel);
14873}
14874
14875static ZigType *adjust_ptr_const(CodeGen *g, ZigType *ptr_type, bool is_const) {
14876 assert(ptr_type->id == ZigTypeIdPointer);
14877 return get_pointer_to_type_extra2(g,
14878 ptr_type->data.pointer.child_type,
14879 is_const, ptr_type->data.pointer.is_volatile,
14880 ptr_type->data.pointer.ptr_len,
14881 ptr_type->data.pointer.explicit_alignment,
14882 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
14883 ptr_type->data.pointer.allow_zero,
14884 ptr_type->data.pointer.vector_index,
14885 ptr_type->data.pointer.inferred_struct_field,
14886 ptr_type->data.pointer.sentinel);
14887}
14888
14889static Error compute_elem_align(IrAnalyze *ira, ZigType *elem_type, uint32_t base_ptr_align,
14890 uint64_t elem_index, uint32_t *result)
14891{
14892 Error err;
14893
14894 if (base_ptr_align == 0) {
14895 *result = 0;
14896 return ErrorNone;
14897 }
14898
14899 // figure out the largest alignment possible
14900 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
14901 return err;
14902
14903 uint64_t elem_size = type_size(ira->codegen, elem_type);
14904 uint64_t abi_align = get_abi_alignment(ira->codegen, elem_type);
14905 uint64_t ptr_align = base_ptr_align;
14906
14907 uint64_t chosen_align = abi_align;
14908 if (ptr_align >= abi_align) {
14909 while (ptr_align > abi_align) {
14910 if ((elem_index * elem_size) % ptr_align == 0) {
14911 chosen_align = ptr_align;
14912 break;
14913 }
14914 ptr_align >>= 1;
14915 }
14916 } else if (elem_size >= ptr_align && elem_size % ptr_align == 0) {
14917 chosen_align = ptr_align;
14918 } else {
14919 // can't get here because guaranteed elem_size >= abi_align
14920 zig_unreachable();
14921 }
14922
14923 *result = chosen_align;
14924 return ErrorNone;
14925}
14926
14927static Stage1AirInst *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, Stage1ZirInstElemPtr *elem_ptr_instruction) {
14928 Error err;
14929 Stage1AirInst *array_ptr = elem_ptr_instruction->array_ptr->child;
14930 if (type_is_invalid(array_ptr->value->type))
14931 return ira->codegen->invalid_inst_gen;
14932
14933 Stage1AirInst *elem_index = elem_ptr_instruction->elem_index->child;
14934 if (type_is_invalid(elem_index->value->type))
14935 return ira->codegen->invalid_inst_gen;
14936
14937 ZigValue *orig_array_ptr_val = array_ptr->value;
14938
14939 ZigType *ptr_type = orig_array_ptr_val->type;
14940 assert(ptr_type->id == ZigTypeIdPointer);
14941
14942 ZigType *array_type = ptr_type->data.pointer.child_type;
14943
14944 // At first return_type will be the pointer type we want to return, except with an optimistic alignment.
14945 // We will adjust return_type's alignment before returning it.
14946 ZigType *return_type;
14947
14948 if (type_is_invalid(array_type))
14949 return ira->codegen->invalid_inst_gen;
14950
14951 if (array_type->id == ZigTypeIdPointer &&
14952 array_type->data.pointer.ptr_len == PtrLenSingle &&
14953 array_type->data.pointer.child_type->id == ZigTypeIdArray)
14954 {
14955 Stage1AirInst *ptr_value = ir_get_deref(ira, elem_ptr_instruction->base.scope,
14956 elem_ptr_instruction->base.source_node, array_ptr, nullptr);
14957 if (type_is_invalid(ptr_value->value->type))
14958 return ira->codegen->invalid_inst_gen;
14959
14960 array_type = array_type->data.pointer.child_type;
14961 ptr_type = ptr_type->data.pointer.child_type;
14962
14963 orig_array_ptr_val = ptr_value->value;
14964 }
14965
14966 if (array_type->id == ZigTypeIdArray) {
14967 if(array_type->data.array.len == 0 && array_type->data.array.sentinel == nullptr){
14968 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
14969 buf_sprintf("accessing a zero length array is not allowed"));
14970 return ira->codegen->invalid_inst_gen;
14971 }
14972
14973 ZigType *child_type = array_type->data.array.child_type;
14974 if (ptr_type->data.pointer.host_int_bytes == 0) {
14975 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
14976 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
14977 elem_ptr_instruction->ptr_len,
14978 ptr_type->data.pointer.explicit_alignment, 0, 0, false);
14979 } else {
14980 uint64_t elem_val_scalar;
14981 if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar))
14982 return ira->codegen->invalid_inst_gen;
14983
14984 size_t bit_width = type_size_bits(ira->codegen, child_type);
14985 size_t bit_offset = bit_width * elem_val_scalar;
14986
14987 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
14988 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
14989 elem_ptr_instruction->ptr_len,
14990 1, (uint32_t)bit_offset, ptr_type->data.pointer.host_int_bytes, false);
14991 }
14992 } else if (array_type->id == ZigTypeIdPointer) {
14993 if (array_type->data.pointer.ptr_len == PtrLenSingle) {
14994 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
14995 buf_sprintf("index of single-item pointer"));
14996 return ira->codegen->invalid_inst_gen;
14997 }
14998 return_type = adjust_ptr_len(ira->codegen, array_type, elem_ptr_instruction->ptr_len);
14999 } else if (is_slice(array_type)) {
15000 return_type = adjust_ptr_len(ira->codegen, array_type->data.structure.fields[slice_ptr_index]->type_entry,
15001 elem_ptr_instruction->ptr_len);
15002 } else if (array_type->id == ZigTypeIdVector) {
15003 // This depends on whether the element index is comptime, so it is computed later.
15004 return_type = nullptr;
15005 } else if (elem_ptr_instruction->init_array_type_source_node != nullptr &&
15006 array_type->id == ZigTypeIdStruct &&
15007 array_type->data.structure.resolve_status == ResolveStatusBeingInferred)
15008 {
15009 ZigType *usize = ira->codegen->builtin_types.entry_usize;
15010 Stage1AirInst *casted_elem_index = ir_implicit_cast(ira, elem_index, usize);
15011 if (type_is_invalid(casted_elem_index->value->type))
15012 return ira->codegen->invalid_inst_gen;
15013 src_assert(instr_is_comptime(casted_elem_index), elem_ptr_instruction->base.source_node);
15014 Buf *field_name = buf_alloc();
15015 bigint_append_buf(field_name, &casted_elem_index->value->data.x_bigint, 10);
15016 return ir_analyze_inferred_field_ptr(ira, field_name, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node,
15017 array_ptr, array_type);
15018 } else if (is_tuple(array_type)) {
15019 uint64_t elem_index_scalar;
15020 if (!ir_resolve_usize(ira, elem_index, &elem_index_scalar))
15021 return ira->codegen->invalid_inst_gen;
15022 if (elem_index_scalar >= array_type->data.structure.src_field_count) {
15023 ir_add_error_node(ira, elem_ptr_instruction->base.source_node, buf_sprintf(
15024 "field index %" ZIG_PRI_u64 " outside tuple '%s' which has %" PRIu32 " fields",
15025 elem_index_scalar, buf_ptr(&array_type->name),
15026 array_type->data.structure.src_field_count));
15027 return ira->codegen->invalid_inst_gen;
15028 }
15029 TypeStructField *field = array_type->data.structure.fields[elem_index_scalar];
15030 return ir_analyze_struct_field_ptr(ira, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node, field, array_ptr,
15031 array_type, false);
15032 } else {
15033 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
15034 buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));
15035 return ira->codegen->invalid_inst_gen;
15036 }
15037
15038 ZigType *usize = ira->codegen->builtin_types.entry_usize;
15039 Stage1AirInst *casted_elem_index = ir_implicit_cast(ira, elem_index, usize);
15040 if (type_is_invalid(casted_elem_index->value->type))
15041 return ira->codegen->invalid_inst_gen;
15042
15043 bool safety_check_on = elem_ptr_instruction->safety_check_on;
15044 if (instr_is_comptime(casted_elem_index)) {
15045 ZigValue *index_val = ir_resolve_const(ira, casted_elem_index, UndefBad);
15046 if (index_val == nullptr)
15047 return ira->codegen->invalid_inst_gen;
15048 uint64_t index = bigint_as_u64(&index_val->data.x_bigint);
15049
15050 if (array_type->id == ZigTypeIdArray) {
15051 uint64_t array_len = array_type->data.array.len +
15052 (array_type->data.array.sentinel != nullptr);
15053 if (index >= array_len) {
15054 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
15055 buf_sprintf("index %" ZIG_PRI_u64 " outside array of size %" ZIG_PRI_u64,
15056 index, array_len));
15057 return ira->codegen->invalid_inst_gen;
15058 }
15059 safety_check_on = false;
15060 } else if (array_type->id == ZigTypeIdVector) {
15061 uint64_t vector_len = array_type->data.vector.len;
15062 if (index >= vector_len) {
15063 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
15064 buf_sprintf("index %" ZIG_PRI_u64 " outside vector of size %" ZIG_PRI_u64,
15065 index, vector_len));
15066 return ira->codegen->invalid_inst_gen;
15067 }
15068 safety_check_on = false;
15069 }
15070
15071 if (array_type->id == ZigTypeIdVector) {
15072 ZigType *elem_type = array_type->data.vector.elem_type;
15073 uint32_t host_vec_len = array_type->data.vector.len;
15074 return_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
15075 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
15076 elem_ptr_instruction->ptr_len,
15077 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index,
15078 nullptr, nullptr);
15079 } else if (return_type->data.pointer.explicit_alignment != 0) {
15080 uint32_t chosen_align;
15081 if ((err = compute_elem_align(ira, return_type->data.pointer.child_type,
15082 return_type->data.pointer.explicit_alignment, index, &chosen_align)))
15083 {
15084 return ira->codegen->invalid_inst_gen;
15085 }
15086 return_type = adjust_ptr_align(ira->codegen, return_type, chosen_align);
15087 }
15088
15089 // TODO The `array_type->id == ZigTypeIdArray` exception here should not be an exception;
15090 // the `orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar` clause should be omitted completely.
15091 // However there are bugs to fix before this improvement can be made.
15092 if (orig_array_ptr_val->special != ConstValSpecialRuntime &&
15093 orig_array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
15094 (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar || array_type->id == ZigTypeIdArray))
15095 {
15096 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec,
15097 elem_ptr_instruction->base.source_node, orig_array_ptr_val, UndefBad)))
15098 {
15099 return ira->codegen->invalid_inst_gen;
15100 }
15101
15102 ZigValue *array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val,
15103 elem_ptr_instruction->base.source_node);
15104 if (array_ptr_val == nullptr)
15105 return ira->codegen->invalid_inst_gen;
15106
15107 if (array_ptr_val->special == ConstValSpecialUndef &&
15108 elem_ptr_instruction->init_array_type_source_node != nullptr)
15109 {
15110 if (array_type->id == ZigTypeIdArray || array_type->id == ZigTypeIdVector) {
15111 array_ptr_val->data.x_array.special = ConstArraySpecialNone;
15112 array_ptr_val->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(array_type->data.array.len);
15113 array_ptr_val->special = ConstValSpecialStatic;
15114 for (size_t i = 0; i < array_type->data.array.len; i += 1) {
15115 ZigValue *elem_val = &array_ptr_val->data.x_array.data.s_none.elements[i];
15116 elem_val->special = ConstValSpecialUndef;
15117 elem_val->type = array_type->data.array.child_type;
15118 elem_val->parent.id = ConstParentIdArray;
15119 elem_val->parent.data.p_array.array_val = array_ptr_val;
15120 elem_val->parent.data.p_array.elem_index = i;
15121 }
15122 } else if (is_slice(array_type)) {
15123 src_assert(array_ptr->value->type->id == ZigTypeIdPointer, elem_ptr_instruction->base.source_node);
15124 ZigType *actual_array_type = array_ptr->value->type->data.pointer.child_type;
15125
15126 if (type_is_invalid(actual_array_type))
15127 return ira->codegen->invalid_inst_gen;
15128 if (actual_array_type->id != ZigTypeIdArray) {
15129 ir_add_error_node(ira, elem_ptr_instruction->init_array_type_source_node,
15130 buf_sprintf("array literal requires address-of operator (&) to coerce to slice type '%s'",
15131 buf_ptr(&actual_array_type->name)));
15132 return ira->codegen->invalid_inst_gen;
15133 }
15134
15135 ZigValue *array_init_val = ira->codegen->pass1_arena->create<ZigValue>();
15136 array_init_val->special = ConstValSpecialStatic;
15137 array_init_val->type = actual_array_type;
15138 array_init_val->data.x_array.special = ConstArraySpecialNone;
15139 array_init_val->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(actual_array_type->data.array.len);
15140 array_init_val->special = ConstValSpecialStatic;
15141 for (size_t i = 0; i < actual_array_type->data.array.len; i += 1) {
15142 ZigValue *elem_val = &array_init_val->data.x_array.data.s_none.elements[i];
15143 elem_val->special = ConstValSpecialUndef;
15144 elem_val->type = actual_array_type->data.array.child_type;
15145 elem_val->parent.id = ConstParentIdArray;
15146 elem_val->parent.data.p_array.array_val = array_init_val;
15147 elem_val->parent.data.p_array.elem_index = i;
15148 }
15149
15150 init_const_slice(ira->codegen, array_ptr_val, array_init_val, 0, actual_array_type->data.array.len,
15151 false, nullptr);
15152 array_ptr_val->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutInfer;
15153 } else {
15154 ir_add_error_node(ira, elem_ptr_instruction->init_array_type_source_node,
15155 buf_sprintf("expected array type or [_], found '%s'",
15156 buf_ptr(&array_type->name)));
15157 return ira->codegen->invalid_inst_gen;
15158 }
15159 }
15160
15161 if (array_ptr_val->special != ConstValSpecialRuntime &&
15162 (array_type->id != ZigTypeIdPointer ||
15163 array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr))
15164 {
15165 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec,
15166 elem_ptr_instruction->base.source_node, array_ptr_val, UndefOk)))
15167 {
15168 return ira->codegen->invalid_inst_gen;
15169 }
15170 if (array_type->id == ZigTypeIdPointer) {
15171 Stage1AirInst *result = ir_const(ira, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node, return_type);
15172 ZigValue *out_val = result->value;
15173 out_val->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
15174 size_t new_index;
15175 size_t mem_size;
15176 size_t old_size;
15177 switch (array_ptr_val->data.x_ptr.special) {
15178 case ConstPtrSpecialInvalid:
15179 case ConstPtrSpecialDiscard:
15180 zig_unreachable();
15181 case ConstPtrSpecialRef:
15182 if (array_ptr_val->data.x_ptr.data.ref.pointee->type->id == ZigTypeIdArray) {
15183 ZigValue *array_val = array_ptr_val->data.x_ptr.data.ref.pointee;
15184 new_index = index;
15185 ZigType *array_type = array_val->type;
15186 mem_size = array_type->data.array.len;
15187 if (array_type->data.array.sentinel != nullptr) {
15188 mem_size += 1;
15189 }
15190 old_size = mem_size;
15191
15192 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
15193 out_val->data.x_ptr.data.base_array.array_val = array_val;
15194 out_val->data.x_ptr.data.base_array.elem_index = new_index;
15195 } else {
15196 mem_size = 1;
15197 old_size = 1;
15198 new_index = index;
15199
15200 out_val->data.x_ptr.special = ConstPtrSpecialRef;
15201 out_val->data.x_ptr.data.ref.pointee = array_ptr_val->data.x_ptr.data.ref.pointee;
15202 }
15203 break;
15204 case ConstPtrSpecialBaseArray:
15205 case ConstPtrSpecialSubArray:
15206 {
15207 size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index;
15208 new_index = offset + index;
15209 ZigType *array_type = array_ptr_val->data.x_ptr.data.base_array.array_val->type;
15210 mem_size = array_type->data.array.len;
15211 if (array_type->data.array.sentinel != nullptr) {
15212 mem_size += 1;
15213 }
15214 old_size = mem_size - offset;
15215
15216 assert(array_ptr_val->data.x_ptr.data.base_array.array_val);
15217
15218 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
15219 out_val->data.x_ptr.data.base_array.array_val =
15220 array_ptr_val->data.x_ptr.data.base_array.array_val;
15221 out_val->data.x_ptr.data.base_array.elem_index = new_index;
15222
15223 break;
15224 }
15225 case ConstPtrSpecialBaseStruct:
15226 zig_panic("TODO elem ptr on a const inner struct");
15227 case ConstPtrSpecialBaseErrorUnionCode:
15228 zig_panic("TODO elem ptr on a const inner error union code");
15229 case ConstPtrSpecialBaseErrorUnionPayload:
15230 zig_panic("TODO elem ptr on a const inner error union payload");
15231 case ConstPtrSpecialBaseOptionalPayload:
15232 zig_panic("TODO elem ptr on a const inner optional payload");
15233 case ConstPtrSpecialHardCodedAddr:
15234 zig_unreachable();
15235 case ConstPtrSpecialFunction:
15236 zig_panic("TODO element ptr of a function casted to a ptr");
15237 case ConstPtrSpecialNull:
15238 zig_panic("TODO elem ptr on a null pointer");
15239 }
15240 if (new_index >= mem_size) {
15241 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
15242 buf_sprintf("index %" ZIG_PRI_u64 " outside pointer of size %" ZIG_PRI_usize "", index, old_size));
15243 return ira->codegen->invalid_inst_gen;
15244 }
15245 return result;
15246 } else if (is_slice(array_type)) {
15247 expand_undef_struct(ira->codegen, array_ptr_val);
15248
15249 ZigValue *ptr_field = array_ptr_val->data.x_struct.fields[slice_ptr_index];
15250 src_assert(ptr_field != nullptr, elem_ptr_instruction->base.source_node);
15251 if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
15252 return ir_build_elem_ptr_gen(ira, elem_ptr_instruction->base.scope,
15253 elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, false,
15254 return_type);
15255 }
15256 ZigValue *len_field = array_ptr_val->data.x_struct.fields[slice_len_index];
15257 Stage1AirInst *result = ir_const(ira, elem_ptr_instruction->base.scope,
15258 elem_ptr_instruction->base.source_node, return_type);
15259 ZigValue *out_val = result->value;
15260 ZigType *slice_ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
15261 uint64_t slice_len = bigint_as_u64(&len_field->data.x_bigint);
15262 uint64_t full_slice_len = slice_len +
15263 ((slice_ptr_type->data.pointer.sentinel != nullptr) ? 1 : 0);
15264 if (index >= full_slice_len) {
15265 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
15266 buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,
15267 index, slice_len));
15268 return ira->codegen->invalid_inst_gen;
15269 }
15270 out_val->data.x_ptr.mut = ptr_field->data.x_ptr.mut;
15271 switch (ptr_field->data.x_ptr.special) {
15272 case ConstPtrSpecialInvalid:
15273 case ConstPtrSpecialDiscard:
15274 zig_unreachable();
15275 case ConstPtrSpecialRef:
15276 out_val->data.x_ptr.special = ConstPtrSpecialRef;
15277 out_val->data.x_ptr.data.ref.pointee = ptr_field->data.x_ptr.data.ref.pointee;
15278 break;
15279 case ConstPtrSpecialSubArray:
15280 case ConstPtrSpecialBaseArray:
15281 {
15282 uint64_t array_len = ptr_field->data.x_ptr.data.base_array.array_val->type->data.array.len;
15283 if (ptr_field->data.x_ptr.data.base_array.array_val->type->data.array.sentinel != nullptr) {
15284 array_len += 1;
15285 }
15286 size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;
15287 uint64_t new_index = offset + index;
15288 if (ptr_field->data.x_ptr.data.base_array.array_val->data.x_array.special !=
15289 ConstArraySpecialBuf)
15290 {
15291 if (new_index >= array_len) {
15292 ir_add_error_node(ira, elem_ptr_instruction->base.source_node, buf_sprintf("out of bounds slice"));
15293 return ira->codegen->invalid_inst_gen;
15294 }
15295 }
15296 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
15297 out_val->data.x_ptr.data.base_array.array_val =
15298 ptr_field->data.x_ptr.data.base_array.array_val;
15299 out_val->data.x_ptr.data.base_array.elem_index = new_index;
15300 break;
15301 }
15302 case ConstPtrSpecialBaseStruct:
15303 zig_panic("TODO elem ptr on a slice backed by const inner struct");
15304 case ConstPtrSpecialBaseErrorUnionCode:
15305 zig_panic("TODO elem ptr on a slice backed by const inner error union code");
15306 case ConstPtrSpecialBaseErrorUnionPayload:
15307 zig_panic("TODO elem ptr on a slice backed by const inner error union payload");
15308 case ConstPtrSpecialBaseOptionalPayload:
15309 zig_panic("TODO elem ptr on a slice backed by const optional payload");
15310 case ConstPtrSpecialHardCodedAddr:
15311 zig_unreachable();
15312 case ConstPtrSpecialFunction:
15313 zig_panic("TODO elem ptr on a slice that was ptrcast from a function");
15314 case ConstPtrSpecialNull:
15315 zig_panic("TODO elem ptr on a slice has a null pointer");
15316 }
15317 return result;
15318 } else if (array_type->id == ZigTypeIdArray || array_type->id == ZigTypeIdVector) {
15319 expand_undef_array(ira->codegen, array_ptr_val);
15320
15321 Stage1AirInst *result;
15322 if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
15323 result = ir_build_elem_ptr_gen(ira, elem_ptr_instruction->base.scope,
15324 elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index,
15325 false, return_type);
15326 result->value->special = ConstValSpecialStatic;
15327 } else {
15328 result = ir_const(ira, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node, return_type);
15329 }
15330 ZigValue *out_val = result->value;
15331 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
15332 out_val->data.x_ptr.mut = orig_array_ptr_val->data.x_ptr.mut;
15333 out_val->data.x_ptr.data.base_array.array_val = array_ptr_val;
15334 out_val->data.x_ptr.data.base_array.elem_index = index;
15335 return result;
15336 } else {
15337 zig_unreachable();
15338 }
15339 }
15340 }
15341 } else if (array_type->id == ZigTypeIdVector) {
15342 // runtime known element index
15343 ZigType *elem_type = array_type->data.vector.elem_type;
15344 uint32_t host_vec_len = array_type->data.vector.len;
15345 return_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
15346 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
15347 elem_ptr_instruction->ptr_len,
15348 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME,
15349 nullptr, nullptr);
15350 } else {
15351 // runtime known element index
15352 switch (type_requires_comptime(ira->codegen, return_type)) {
15353 case ReqCompTimeYes:
15354 ir_add_error(ira, elem_index,
15355 buf_sprintf("values of type '%s' must be comptime known, but index value is runtime known",
15356 buf_ptr(&return_type->data.pointer.child_type->name)));
15357 return ira->codegen->invalid_inst_gen;
15358 case ReqCompTimeInvalid:
15359 return ira->codegen->invalid_inst_gen;
15360 case ReqCompTimeNo:
15361 break;
15362 }
15363
15364 if (return_type->data.pointer.explicit_alignment != 0) {
15365 if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown)))
15366 return ira->codegen->invalid_inst_gen;
15367
15368 uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);
15369 uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);
15370 uint64_t ptr_align = get_ptr_align(ira->codegen, return_type);
15371 if (ptr_align < abi_align) {
15372 if (elem_size >= ptr_align && elem_size % ptr_align == 0) {
15373 return_type = adjust_ptr_align(ira->codegen, return_type, ptr_align);
15374 } else {
15375 // can't get here because guaranteed elem_size >= abi_align
15376 zig_unreachable();
15377 }
15378 } else {
15379 return_type = adjust_ptr_align(ira->codegen, return_type, abi_align);
15380 }
15381 }
15382 }
15383
15384 return ir_build_elem_ptr_gen(ira, elem_ptr_instruction->base.scope,
15385 elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, safety_check_on, return_type);
15386}
15387
15388static Stage1AirInst *ir_analyze_container_member_access_inner(IrAnalyze *ira,
15389 ZigType *bare_struct_type, Buf *field_name, Scope *scope, AstNode *source_node,
15390 Stage1AirInst *container_ptr, AstNode *container_ptr_src, ZigType *container_type)
15391{
15392 if (!is_slice(bare_struct_type)) {
15393 ScopeDecls *container_scope = get_container_scope(bare_struct_type);
15394 assert(container_scope != nullptr);
15395 auto tld = find_container_decl(ira->codegen, container_scope, field_name);
15396 if (tld) {
15397 if (tld->id == TldIdFn) {
15398 resolve_top_level_decl(ira->codegen, tld, source_node, false);
15399 if (tld->resolution == TldResolutionInvalid)
15400 return ira->codegen->invalid_inst_gen;
15401 if (tld->resolution == TldResolutionResolving)
15402 return ir_error_dependency_loop(ira, source_node);
15403
15404 if (tld->visib_mod == VisibModPrivate &&
15405 tld->import != get_scope_import(scope))
15406 {
15407 ErrorMsg *msg = ir_add_error_node(ira, source_node,
15408 buf_sprintf("'%s' is private", buf_ptr(field_name)));
15409 add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("declared here"));
15410 return ira->codegen->invalid_inst_gen;
15411 }
15412
15413 TldFn *tld_fn = (TldFn *)tld;
15414 ZigFn *fn_entry = tld_fn->fn_entry;
15415 assert(fn_entry != nullptr);
15416
15417 if (type_is_invalid(fn_entry->type_entry))
15418 return ira->codegen->invalid_inst_gen;
15419
15420 Stage1AirInst *bound_fn_value = ir_const_bound_fn(ira, scope, source_node, fn_entry, container_ptr,
15421 container_ptr_src);
15422 return ir_get_ref(ira, scope, source_node, bound_fn_value, true, false);
15423 } else if (tld->id == TldIdVar) {
15424 resolve_top_level_decl(ira->codegen, tld, source_node, false);
15425 if (tld->resolution == TldResolutionInvalid)
15426 return ira->codegen->invalid_inst_gen;
15427 if (tld->resolution == TldResolutionResolving)
15428 return ir_error_dependency_loop(ira, source_node);
15429
15430 TldVar *tld_var = (TldVar *)tld;
15431 ZigVar *var = tld_var->var;
15432 assert(var != nullptr);
15433
15434 if (type_is_invalid(var->var_type))
15435 return ira->codegen->invalid_inst_gen;
15436
15437 if (var->const_value->type->id == ZigTypeIdFn) {
15438 src_assert(var->const_value->data.x_ptr.special == ConstPtrSpecialFunction, source_node);
15439 ZigFn *fn = var->const_value->data.x_ptr.data.fn.fn_entry;
15440 Stage1AirInst *bound_fn_value = ir_const_bound_fn(ira, scope, source_node, fn, container_ptr,
15441 container_ptr_src);
15442 return ir_get_ref(ira, scope, source_node, bound_fn_value, true, false);
15443 }
15444 }
15445 }
15446 }
15447 const char *prefix_name;
15448 if (is_slice(bare_struct_type)) {
15449 prefix_name = "";
15450 } else if (bare_struct_type->id == ZigTypeIdStruct) {
15451 prefix_name = "struct ";
15452 } else if (bare_struct_type->id == ZigTypeIdEnum) {
15453 prefix_name = "enum ";
15454 } else if (bare_struct_type->id == ZigTypeIdUnion) {
15455 prefix_name = "union ";
15456 } else if (bare_struct_type->id == ZigTypeIdOpaque) {
15457 prefix_name = "opaque type ";
15458 } else {
15459 prefix_name = "";
15460 }
15461 ir_add_error_node(ira, source_node,
15462 buf_sprintf("no member named '%s' in %s'%s'", buf_ptr(field_name), prefix_name, buf_ptr(&bare_struct_type->name)));
15463 return ira->codegen->invalid_inst_gen;
15464}
15465
15466static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, TypeStructField *field) {
15467 if (field->init_val != nullptr) return;
15468 if (field->decl_node == nullptr) return;
15469 if (field->decl_node->type != NodeTypeStructField) return;
15470 AstNode *init_node = field->decl_node->data.struct_field.value;
15471 if (init_node == nullptr) return;
15472 // scope is not the scope of the struct init, it's the scope of the struct type decl
15473 Scope *analyze_scope = &get_container_scope(container_type)->base;
15474 // memoize it
15475 field->init_val = analyze_const_value(codegen, analyze_scope, init_node,
15476 field->type_entry, nullptr, UndefOk);
15477}
15478
15479static Stage1AirInst *ir_analyze_struct_field_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node,
15480 TypeStructField *field, Stage1AirInst *struct_ptr, ZigType *struct_type, bool initializing)
15481{
15482 Error err;
15483 ZigType *field_type = resolve_struct_field_type(ira->codegen, field);
15484 if (field_type == nullptr)
15485 return ira->codegen->invalid_inst_gen;
15486 if (field->is_comptime) {
15487 Stage1AirInst *elem = ir_const(ira, scope, source_node, field_type);
15488 memoize_field_init_val(ira->codegen, struct_type, field);
15489 if(field->init_val != nullptr && type_is_invalid(field->init_val->type)){
15490 return ira->codegen->invalid_inst_gen;
15491 }
15492 copy_const_val(ira->codegen, elem->value, field->init_val);
15493 return ir_get_ref2(ira, scope, source_node, elem, field_type, true, false);
15494 }
15495 switch (type_has_one_possible_value(ira->codegen, field_type)) {
15496 case OnePossibleValueInvalid:
15497 return ira->codegen->invalid_inst_gen;
15498 case OnePossibleValueYes: {
15499 Stage1AirInst *elem = ir_const_move(ira, scope, source_node,
15500 get_the_one_possible_value(ira->codegen, field_type));
15501 return ir_get_ref(ira, scope, source_node, elem,
15502 struct_ptr->value->type->data.pointer.is_const,
15503 struct_ptr->value->type->data.pointer.is_volatile);
15504 }
15505 case OnePossibleValueNo:
15506 break;
15507 }
15508 bool is_const = struct_ptr->value->type->data.pointer.is_const;
15509 bool is_volatile = struct_ptr->value->type->data.pointer.is_volatile;
15510 ZigType *ptr_type;
15511 if (is_anon_container(struct_type)) {
15512 ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
15513 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
15514 } else {
15515 ResolveStatus needed_resolve_status =
15516 (struct_type->data.structure.layout == ContainerLayoutAuto) ?
15517 ResolveStatusZeroBitsKnown : ResolveStatusSizeKnown;
15518 if ((err = type_resolve(ira->codegen, struct_type, needed_resolve_status)))
15519 return ira->codegen->invalid_inst_gen;
15520 assert(struct_ptr->value->type->id == ZigTypeIdPointer);
15521 uint32_t ptr_bit_offset = struct_ptr->value->type->data.pointer.bit_offset_in_host;
15522 uint32_t ptr_host_int_bytes = struct_ptr->value->type->data.pointer.host_int_bytes;
15523 if (ptr_host_int_bytes > 0) {
15524 ptr_bit_offset += field->offset * 8;
15525 }
15526 uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
15527 get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes;
15528 ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
15529 is_const, is_volatile, PtrLenSingle, field->align,
15530 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
15531 (uint32_t)host_int_bytes_for_result_type, false);
15532
15533 if (field == struct_type->data.structure.misaligned_field) {
15534 // If field is the last single misaligned field it will be represented as array
15535 // of bytes in LLVM but get_pointer_to_type_extra will set its host_int_bytes to 0.
15536 // We need it not to be 0 so later stage would generate proper bit casting code.
15537 ptr_type->data.pointer.host_int_bytes = host_int_bytes_for_result_type;
15538 }
15539 }
15540 if (instr_is_comptime(struct_ptr)) {
15541 ZigValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad);
15542 if (!ptr_val)
15543 return ira->codegen->invalid_inst_gen;
15544
15545 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
15546 ZigValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_node);
15547 if (struct_val == nullptr)
15548 return ira->codegen->invalid_inst_gen;
15549 if (type_is_invalid(struct_val->type))
15550 return ira->codegen->invalid_inst_gen;
15551
15552 // This to allow lazy values to be resolved.
15553 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec,
15554 source_node, struct_val, UndefOk)))
15555 {
15556 return ira->codegen->invalid_inst_gen;
15557 }
15558 if (initializing && struct_val->special == ConstValSpecialUndef) {
15559 struct_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, struct_type->data.structure.src_field_count);
15560 struct_val->special = ConstValSpecialStatic;
15561 for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
15562 if (struct_type->data.structure.fields[i]->is_comptime)
15563 continue;
15564 ZigValue *field_val = struct_val->data.x_struct.fields[i];
15565 field_val->special = ConstValSpecialUndef;
15566 field_val->type = resolve_struct_field_type(ira->codegen,
15567 struct_type->data.structure.fields[i]);
15568 field_val->parent.id = ConstParentIdStruct;
15569 field_val->parent.data.p_struct.struct_val = struct_val;
15570 field_val->parent.data.p_struct.field_index = i;
15571 }
15572 }
15573 Stage1AirInst *result;
15574 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
15575 result = ir_build_struct_field_ptr(ira, scope, source_node, struct_ptr, field, ptr_type);
15576 result->value->special = ConstValSpecialStatic;
15577 } else {
15578 result = ir_const(ira, scope, source_node, ptr_type);
15579 }
15580 ZigValue *const_val = result->value;
15581 const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
15582 const_val->data.x_ptr.mut = ptr_val->data.x_ptr.mut;
15583 const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
15584 const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
15585 return result;
15586 }
15587 }
15588 return ir_build_struct_field_ptr(ira, scope, source_node, struct_ptr, field, ptr_type);
15589}
15590
15591static Stage1AirInst *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name,
15592 Scope *scope, AstNode *source_node, Stage1AirInst *container_ptr, ZigType *container_type)
15593{
15594 // The type of the field is not available until a store using this pointer happens.
15595 // So, here we create a special pointer type which has the inferred struct type and
15596 // field name encoded in the type. Later, when there is a store via this pointer,
15597 // the field type will then be available, and the field will be added to the inferred
15598 // struct.
15599
15600 ZigType *container_ptr_type = container_ptr->value->type;
15601 src_assert(container_ptr_type->id == ZigTypeIdPointer, source_node);
15602
15603 InferredStructField *inferred_struct_field = heap::c_allocator.create<InferredStructField>();
15604 inferred_struct_field->inferred_struct_type = container_type;
15605 inferred_struct_field->field_name = field_name;
15606
15607 ZigType *elem_type = ira->codegen->builtin_types.entry_anytype;
15608 ZigType *field_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
15609 container_ptr_type->data.pointer.is_const, container_ptr_type->data.pointer.is_volatile,
15610 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field, nullptr);
15611
15612 if (instr_is_comptime(container_ptr)) {
15613 ZigValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
15614 if (ptr_val == nullptr)
15615 return ira->codegen->invalid_inst_gen;
15616
15617 Stage1AirInst *result;
15618 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
15619 result = ir_build_cast(ira, scope, source_node, container_ptr_type, container_ptr, CastOpNoop);
15620 } else {
15621 result = ir_const(ira, scope, source_node, field_ptr_type);
15622 }
15623 copy_const_val(ira->codegen, result->value, ptr_val);
15624 result->value->type = field_ptr_type;
15625 return result;
15626 }
15627
15628 return ir_build_cast(ira, scope, source_node, field_ptr_type, container_ptr, CastOpNoop);
15629}
15630
15631static Stage1AirInst *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
15632 Scope *scope, AstNode *source_node, Stage1AirInst *container_ptr, AstNode *container_ptr_src,
15633 ZigType *container_type, bool initializing)
15634{
15635 Error err;
15636
15637 ZigType *bare_type = container_ref_type(container_type);
15638
15639 if (initializing && bare_type->id == ZigTypeIdStruct &&
15640 bare_type->data.structure.resolve_status == ResolveStatusBeingInferred)
15641 {
15642 return ir_analyze_inferred_field_ptr(ira, field_name, scope, source_node, container_ptr, bare_type);
15643 }
15644
15645 // Tracks whether we should return an undefined value of the correct type.
15646 // We do this if the container pointer is undefined and we are in a TypeOf call.
15647 bool return_undef = container_ptr->value->special == ConstValSpecialUndef && \
15648 get_scope_typeof(scope) != nullptr;
15649
15650 if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown)))
15651 return ira->codegen->invalid_inst_gen;
15652
15653 assert(container_ptr->value->type->id == ZigTypeIdPointer);
15654 if (bare_type->id == ZigTypeIdStruct) {
15655 TypeStructField *field = find_struct_type_field(bare_type, field_name);
15656 if (field != nullptr) {
15657 if (return_undef) {
15658 ZigType *field_ptr_type = get_pointer_to_type(ira->codegen, resolve_struct_field_type(ira->codegen, field),
15659 container_ptr->value->type->data.pointer.is_const);
15660 return ir_const_undef(ira, scope, source_node, field_ptr_type);
15661 }
15662
15663 return ir_analyze_struct_field_ptr(ira, scope, source_node, field, container_ptr, bare_type, initializing);
15664 } else {
15665 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
15666 scope, source_node, container_ptr, container_ptr_src, container_type);
15667 }
15668 }
15669
15670 if (bare_type->id == ZigTypeIdEnum || bare_type->id == ZigTypeIdOpaque) {
15671 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
15672 scope, source_node, container_ptr, container_ptr_src, container_type);
15673 }
15674
15675 if (bare_type->id == ZigTypeIdUnion) {
15676 bool is_const = container_ptr->value->type->data.pointer.is_const;
15677 bool is_volatile = container_ptr->value->type->data.pointer.is_volatile;
15678
15679 TypeUnionField *field = find_union_type_field(bare_type, field_name);
15680 if (field == nullptr) {
15681 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
15682 scope, source_node, container_ptr, container_ptr_src, container_type);
15683 }
15684
15685 ZigType *field_type = resolve_union_field_type(ira->codegen, field);
15686 if (field_type == nullptr)
15687 return ira->codegen->invalid_inst_gen;
15688
15689 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
15690 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
15691 if (instr_is_comptime(container_ptr)) {
15692 ZigValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
15693 if (!ptr_val)
15694 return ira->codegen->invalid_inst_gen;
15695
15696 if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar &&
15697 ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
15698 ZigValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_node);
15699 if (union_val == nullptr)
15700 return ira->codegen->invalid_inst_gen;
15701 if (type_is_invalid(union_val->type))
15702 return ira->codegen->invalid_inst_gen;
15703
15704 // Reject undefined values unless we're initializing the union:
15705 // a undefined union means also the tag is undefined, accessing
15706 // its payload slot is UB.
15707 const UndefAllowed allow_undef = initializing ? UndefOk : UndefBad;
15708 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec,
15709 source_node, union_val, allow_undef)))
15710 {
15711 return ira->codegen->invalid_inst_gen;
15712 }
15713
15714 if (initializing) {
15715 ZigValue *payload_val = ira->codegen->pass1_arena->create<ZigValue>();
15716 payload_val->special = ConstValSpecialUndef;
15717 payload_val->type = field_type;
15718 payload_val->parent.id = ConstParentIdUnion;
15719 payload_val->parent.data.p_union.union_val = union_val;
15720
15721 union_val->special = ConstValSpecialStatic;
15722 bigint_init_bigint(&union_val->data.x_union.tag, &field->enum_field->value);
15723 union_val->data.x_union.payload = payload_val;
15724 } else if (bare_type->data.unionation.layout != ContainerLayoutExtern) {
15725 TypeUnionField *actual_field = find_union_field_by_tag(bare_type, &union_val->data.x_union.tag);
15726 if (actual_field == nullptr)
15727 zig_unreachable();
15728
15729 if (field != actual_field) {
15730 ir_add_error_node(ira, source_node,
15731 buf_sprintf("accessing union field '%s' while field '%s' is set", buf_ptr(field_name),
15732 buf_ptr(actual_field->name)));
15733 return ira->codegen->invalid_inst_gen;
15734 }
15735 }
15736
15737 ZigValue *payload_val = union_val->data.x_union.payload;
15738 assert(payload_val);
15739
15740 Stage1AirInst *result;
15741 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
15742 result = ir_build_union_field_ptr(ira, scope, source_node, container_ptr, field, true,
15743 initializing, ptr_type);
15744 result->value->special = ConstValSpecialStatic;
15745 } else {
15746 result = ir_const(ira, scope, source_node, ptr_type);
15747 }
15748 ZigValue *const_val = result->value;
15749 const_val->data.x_ptr.special = ConstPtrSpecialRef;
15750 const_val->data.x_ptr.mut = container_ptr->value->data.x_ptr.mut;
15751 const_val->data.x_ptr.data.ref.pointee = payload_val;
15752 return result;
15753 }
15754 }
15755
15756 return ir_build_union_field_ptr(ira, scope, source_node, container_ptr, field, true, initializing, ptr_type);
15757 }
15758
15759 zig_unreachable();
15760}
15761
15762static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, AstNode *source_node) {
15763 const char *msg = stage2_add_link_lib(&ira->codegen->stage1, buf_ptr(lib_name), buf_len(lib_name),
15764 buf_ptr(symbol_name), buf_len(symbol_name));
15765 if (msg != nullptr) {
15766 ir_add_error_node(ira, source_node, buf_create_from_str(msg));
15767 ira->codegen->reported_bad_link_libc_error = true;
15768 }
15769}
15770
15771static Stage1AirInst *ir_error_dependency_loop(IrAnalyze *ira, AstNode* source_node) {
15772 ir_add_error_node(ira, source_node, buf_sprintf("dependency loop detected"));
15773 return ira->codegen->invalid_inst_gen;
15774}
15775
15776static Stage1AirInst *ir_analyze_decl_ref(IrAnalyze *ira, Scope *scope, AstNode *source_node, Tld *tld) {
15777 resolve_top_level_decl(ira->codegen, tld, source_node, true);
15778 if (tld->resolution == TldResolutionInvalid) {
15779 return ira->codegen->invalid_inst_gen;
15780 }
15781 if (tld->resolution == TldResolutionResolving)
15782 return ir_error_dependency_loop(ira, source_node);
15783
15784 switch (tld->id) {
15785 case TldIdContainer:
15786 case TldIdCompTime:
15787 case TldIdUsingNamespace:
15788 zig_unreachable();
15789 case TldIdVar: {
15790 TldVar *tld_var = (TldVar *)tld;
15791 ZigVar *var = tld_var->var;
15792 assert(var != nullptr);
15793
15794 if (tld_var->extern_lib_name != nullptr) {
15795 add_link_lib_symbol(ira, tld_var->extern_lib_name, buf_create_from_str(var->name),
15796 source_node);
15797 }
15798
15799 return ir_get_var_ptr(ira, scope, source_node, var);
15800 }
15801 case TldIdFn: {
15802 TldFn *tld_fn = (TldFn *)tld;
15803 ZigFn *fn_entry = tld_fn->fn_entry;
15804 assert(fn_entry->type_entry != nullptr);
15805
15806 if (type_is_invalid(fn_entry->type_entry))
15807 return ira->codegen->invalid_inst_gen;
15808
15809 if (tld_fn->extern_lib_name != nullptr) {
15810 add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, source_node);
15811 }
15812
15813 Stage1AirInst *fn_inst = ir_const_fn(ira, scope, source_node, fn_entry);
15814 return ir_get_ref(ira, scope, source_node, fn_inst, true, false);
15815 }
15816 }
15817 zig_unreachable();
15818}
15819
15820static ErrorTableEntry *find_err_table_entry(ZigType *err_set_type, Buf *field_name) {
15821 assert(err_set_type->id == ZigTypeIdErrorSet);
15822 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
15823 ErrorTableEntry *err_table_entry = err_set_type->data.error_set.errors[i];
15824 if (buf_eql_buf(&err_table_entry->name, field_name)) {
15825 return err_table_entry;
15826 }
15827 }
15828 return nullptr;
15829}
15830
15831static Stage1AirInst *ir_analyze_instruction_field_ptr(IrAnalyze *ira, Stage1ZirInstFieldPtr *field_ptr_instruction) {
15832 Error err;
15833 Stage1AirInst *container_ptr = field_ptr_instruction->container_ptr->child;
15834 if (type_is_invalid(container_ptr->value->type))
15835 return ira->codegen->invalid_inst_gen;
15836
15837 ZigType *container_type = container_ptr->value->type->data.pointer.child_type;
15838
15839 Buf *field_name = field_ptr_instruction->field_name_buffer;
15840 if (!field_name) {
15841 Stage1AirInst *field_name_expr = field_ptr_instruction->field_name_expr->child;
15842 field_name = ir_resolve_str(ira, field_name_expr);
15843 if (!field_name)
15844 return ira->codegen->invalid_inst_gen;
15845 }
15846
15847
15848 AstNode *source_node = field_ptr_instruction->base.source_node;
15849
15850 if (type_is_invalid(container_type)) {
15851 return ira->codegen->invalid_inst_gen;
15852 } else if (is_tuple(container_type) && !field_ptr_instruction->initializing && buf_eql_str(field_name, "len")) {
15853 Stage1AirInst *len_inst = ir_const_unsigned(ira, field_ptr_instruction->base.scope, field_ptr_instruction->base.source_node,
15854 container_type->data.structure.src_field_count);
15855 return ir_get_ref(ira, field_ptr_instruction->base.scope, field_ptr_instruction->base.source_node, len_inst, true, false);
15856 } else if (is_slice(container_type) || is_container_ref(container_type)) {
15857 assert(container_ptr->value->type->id == ZigTypeIdPointer);
15858 if (container_type->id == ZigTypeIdPointer) {
15859 ZigType *bare_type = container_ref_type(container_type);
15860 Stage1AirInst *container_child = ir_get_deref(ira, field_ptr_instruction->base.scope,
15861 field_ptr_instruction->base.source_node, container_ptr, nullptr);
15862 Stage1AirInst *result = ir_analyze_container_field_ptr(ira, field_name,
15863 field_ptr_instruction->base.scope, field_ptr_instruction->base.source_node,
15864 container_child, field_ptr_instruction->container_ptr->source_node, bare_type,
15865 field_ptr_instruction->initializing);
15866 return result;
15867 } else {
15868 Stage1AirInst *result = ir_analyze_container_field_ptr(ira, field_name,
15869 field_ptr_instruction->base.scope, field_ptr_instruction->base.source_node,
15870 container_ptr, field_ptr_instruction->container_ptr->source_node,
15871 container_type, field_ptr_instruction->initializing);
15872 return result;
15873 }
15874 } else if (is_array_ref(container_type) && !field_ptr_instruction->initializing) {
15875 if (buf_eql_str(field_name, "len")) {
15876 ZigValue *len_val = ira->codegen->pass1_arena->create<ZigValue>();
15877 if (container_type->id == ZigTypeIdPointer) {
15878 init_const_usize(ira->codegen, len_val, container_type->data.pointer.child_type->data.array.len);
15879 } else {
15880 init_const_usize(ira->codegen, len_val, container_type->data.array.len);
15881 }
15882
15883 ZigType *usize = ira->codegen->builtin_types.entry_usize;
15884 bool ptr_is_const = true;
15885 bool ptr_is_volatile = false;
15886 return ir_get_const_ptr(ira, field_ptr_instruction->base.scope, field_ptr_instruction->base.source_node, len_val,
15887 usize, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
15888 } else {
15889 ir_add_error_node(ira, source_node,
15890 buf_sprintf("no field named '%s' in '%s'", buf_ptr(field_name),
15891 buf_ptr(&container_type->name)));
15892 return ira->codegen->invalid_inst_gen;
15893 }
15894 } else if (container_type->id == ZigTypeIdMetaType) {
15895 ZigValue *container_ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
15896 if (!container_ptr_val)
15897 return ira->codegen->invalid_inst_gen;
15898
15899 assert(container_ptr->value->type->id == ZigTypeIdPointer);
15900 ZigValue *child_val = const_ptr_pointee(ira, ira->codegen, container_ptr_val, source_node);
15901 if (child_val == nullptr)
15902 return ira->codegen->invalid_inst_gen;
15903 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec,
15904 field_ptr_instruction->base.source_node, child_val, UndefBad)))
15905 {
15906 return ira->codegen->invalid_inst_gen;
15907 }
15908 ZigType *child_type = child_val->data.x_type;
15909
15910 if (type_is_invalid(child_type)) {
15911 return ira->codegen->invalid_inst_gen;
15912 } else if (is_container(child_type)) {
15913 if (child_type->id == ZigTypeIdEnum) {
15914 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
15915 return ira->codegen->invalid_inst_gen;
15916
15917 TypeEnumField *field = find_enum_type_field(child_type, field_name);
15918 if (field) {
15919 bool ptr_is_const = true;
15920 bool ptr_is_volatile = false;
15921 return ir_get_const_ptr(ira, field_ptr_instruction->base.scope, field_ptr_instruction->base.source_node,
15922 create_const_enum(ira->codegen, child_type, &field->value), child_type,
15923 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
15924 }
15925 }
15926 ScopeDecls *container_scope = get_container_scope(child_type);
15927 Tld *tld = find_container_decl(ira->codegen, container_scope, field_name);
15928 if (tld) {
15929 if (tld->visib_mod == VisibModPrivate &&
15930 tld->import != get_scope_import(field_ptr_instruction->base.scope))
15931 {
15932 ErrorMsg *msg = ir_add_error_node(ira, field_ptr_instruction->base.source_node,
15933 buf_sprintf("'%s' is private", buf_ptr(field_name)));
15934 add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("declared here"));
15935 return ira->codegen->invalid_inst_gen;
15936 }
15937 return ir_analyze_decl_ref(ira, field_ptr_instruction->base.scope, field_ptr_instruction->base.source_node, tld);
15938 }
15939 if (is_tagged_union(child_type)) {
15940 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
15941 return ira->codegen->invalid_inst_gen;
15942 TypeUnionField *field = find_union_type_field(child_type, field_name);
15943 if (field) {
15944 ZigType *enum_type = child_type->data.unionation.tag_type;
15945 bool ptr_is_const = true;
15946 bool ptr_is_volatile = false;
15947 return ir_get_const_ptr(ira, field_ptr_instruction->base.scope, field_ptr_instruction->base.source_node,
15948 create_const_enum(ira->codegen, enum_type, &field->enum_field->value), enum_type,
15949 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
15950 }
15951 }
15952 const char *container_name = (child_type == ira->codegen->root_import) ?
15953 "root source file" : buf_ptr(buf_sprintf("container '%s'", buf_ptr(&child_type->name)));
15954 ir_add_error_node(ira, field_ptr_instruction->base.source_node,
15955 buf_sprintf("%s has no member called '%s'",
15956 container_name, buf_ptr(field_name)));
15957 return ira->codegen->invalid_inst_gen;
15958 } else if (child_type->id == ZigTypeIdErrorSet) {
15959 ErrorTableEntry *err_entry;
15960 ZigType *err_set_type;
15961 if (type_is_global_error_set(child_type)) {
15962 auto existing_entry = ira->codegen->error_table.maybe_get(field_name);
15963 if (existing_entry) {
15964 err_entry = existing_entry->value;
15965 } else {
15966 err_entry = heap::c_allocator.create<ErrorTableEntry>();
15967 err_entry->decl_node = field_ptr_instruction->base.source_node;
15968 buf_init_from_buf(&err_entry->name, field_name);
15969 size_t error_value_count = ira->codegen->errors_by_index.length;
15970 assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)ira->codegen->err_tag_type->data.integral.bit_count));
15971 err_entry->value = error_value_count;
15972 ira->codegen->errors_by_index.append(err_entry);
15973 ira->codegen->error_table.put(field_name, err_entry);
15974 }
15975 if (err_entry->set_with_only_this_in_it == nullptr) {
15976 err_entry->set_with_only_this_in_it = make_err_set_with_one_item(ira->codegen,
15977 field_ptr_instruction->base.scope, field_ptr_instruction->base.source_node,
15978 err_entry);
15979 }
15980 err_set_type = err_entry->set_with_only_this_in_it;
15981 } else {
15982 if (!resolve_inferred_error_set(ira->codegen, child_type, field_ptr_instruction->base.source_node)) {
15983 return ira->codegen->invalid_inst_gen;
15984 }
15985 err_entry = find_err_table_entry(child_type, field_name);
15986 if (err_entry == nullptr) {
15987 ir_add_error_node(ira, field_ptr_instruction->base.source_node,
15988 buf_sprintf("no error named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&child_type->name)));
15989 return ira->codegen->invalid_inst_gen;
15990 }
15991 err_set_type = child_type;
15992 }
15993 ZigValue *const_val = ira->codegen->pass1_arena->create<ZigValue>();
15994 const_val->special = ConstValSpecialStatic;
15995 const_val->type = err_set_type;
15996 const_val->data.x_err_set = err_entry;
15997
15998 bool ptr_is_const = true;
15999 bool ptr_is_volatile = false;
16000 return ir_get_const_ptr(ira, field_ptr_instruction->base.scope,
16001 field_ptr_instruction->base.source_node, const_val,
16002 err_set_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
16003 } else {
16004 ir_add_error_node(ira, field_ptr_instruction->base.source_node,
16005 buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name)));
16006 return ira->codegen->invalid_inst_gen;
16007 }
16008 } else if (field_ptr_instruction->initializing) {
16009 ir_add_error_node(ira, field_ptr_instruction->base.source_node,
16010 buf_sprintf("type '%s' does not support struct initialization syntax", buf_ptr(&container_type->name)));
16011 return ira->codegen->invalid_inst_gen;
16012 } else {
16013 ir_add_error_node(ira, field_ptr_instruction->base.source_node,
16014 buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name)));
16015 return ira->codegen->invalid_inst_gen;
16016 }
16017}
16018
16019static Stage1AirInst *ir_analyze_instruction_store_ptr(IrAnalyze *ira, Stage1ZirInstStorePtr *instruction) {
16020 Stage1AirInst *ptr = instruction->ptr->child;
16021 if (type_is_invalid(ptr->value->type))
16022 return ira->codegen->invalid_inst_gen;
16023
16024 Stage1AirInst *value = instruction->value->child;
16025 if (type_is_invalid(value->value->type))
16026 return ira->codegen->invalid_inst_gen;
16027
16028 return ir_analyze_store_ptr(ira, instruction->base.scope, instruction->base.source_node, ptr, value, instruction->allow_write_through_const);
16029}
16030
16031static Stage1AirInst *ir_analyze_instruction_load_ptr(IrAnalyze *ira, Stage1ZirInstLoadPtr *instruction) {
16032 Stage1AirInst *ptr = instruction->ptr->child;
16033 if (type_is_invalid(ptr->value->type))
16034 return ira->codegen->invalid_inst_gen;
16035 return ir_get_deref(ira, instruction->base.scope, instruction->base.source_node, ptr, nullptr);
16036}
16037
16038static Stage1AirInst *ir_analyze_instruction_typeof(IrAnalyze *ira, Stage1ZirInstTypeOf *typeof_instruction) {
16039 ZigType *type_entry;
16040
16041 const size_t value_count = typeof_instruction->value_count;
16042
16043 // Fast path for the common case of TypeOf with a single argument
16044 if (value_count < 2) {
16045 type_entry = typeof_instruction->value.scalar->child->value->type;
16046 } else {
16047 Stage1AirInst **args = heap::c_allocator.allocate<Stage1AirInst*>(value_count);
16048 for (size_t i = 0; i < value_count; i += 1) {
16049 Stage1AirInst *value = typeof_instruction->value.list[i]->child;
16050 if (type_is_invalid(value->value->type))
16051 return ira->codegen->invalid_inst_gen;
16052 args[i] = value;
16053 }
16054
16055 type_entry = ir_resolve_peer_types(ira, typeof_instruction->base.source_node,
16056 nullptr, args, value_count);
16057
16058 heap::c_allocator.deallocate(args, value_count);
16059 }
16060
16061 if (type_is_invalid(type_entry))
16062 return ira->codegen->invalid_inst_gen;
16063
16064 return ir_const_type(ira, typeof_instruction->base.scope, typeof_instruction->base.source_node, type_entry);
16065}
16066
16067static Stage1AirInst *ir_analyze_instruction_set_cold(IrAnalyze *ira, Stage1ZirInstSetCold *instruction) {
16068 if (ira->new_irb.exec->is_inline) {
16069 // ignore setCold when running functions at compile time
16070 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
16071 }
16072
16073 Stage1AirInst *is_cold_value = instruction->is_cold->child;
16074 bool want_cold;
16075 if (!ir_resolve_bool(ira, is_cold_value, &want_cold))
16076 return ira->codegen->invalid_inst_gen;
16077
16078 ZigFn *fn_entry = scope_fn_entry(instruction->base.scope);
16079 if (fn_entry == nullptr) {
16080 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("@setCold outside function"));
16081 return ira->codegen->invalid_inst_gen;
16082 }
16083
16084 if (fn_entry->set_cold_node != nullptr) {
16085 ErrorMsg *msg = ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("cold set twice in same function"));
16086 add_error_note(ira->codegen, msg, fn_entry->set_cold_node, buf_sprintf("first set here"));
16087 return ira->codegen->invalid_inst_gen;
16088 }
16089
16090 fn_entry->set_cold_node = instruction->base.source_node;
16091 fn_entry->is_cold = want_cold;
16092
16093 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
16094}
16095
16096static Stage1AirInst *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira,
16097 Stage1ZirInstSetRuntimeSafety *set_runtime_safety_instruction)
16098{
16099 if (ira->new_irb.exec->is_inline) {
16100 // ignore setRuntimeSafety when running functions at compile time
16101 return ir_const_void(ira, set_runtime_safety_instruction->base.scope,
16102 set_runtime_safety_instruction->base.source_node);
16103 }
16104
16105 bool *safety_off_ptr;
16106 AstNode **safety_set_node_ptr;
16107
16108 Scope *scope = set_runtime_safety_instruction->base.scope;
16109 while (scope != nullptr) {
16110 if (scope->id == ScopeIdBlock) {
16111 ScopeBlock *block_scope = (ScopeBlock *)scope;
16112 safety_off_ptr = &block_scope->safety_off;
16113 safety_set_node_ptr = &block_scope->safety_set_node;
16114 break;
16115 } else if (scope->id == ScopeIdFnDef) {
16116 ScopeFnDef *def_scope = (ScopeFnDef *)scope;
16117 ZigFn *target_fn = def_scope->fn_entry;
16118 assert(target_fn->def_scope != nullptr);
16119 safety_off_ptr = &target_fn->def_scope->safety_off;
16120 safety_set_node_ptr = &target_fn->def_scope->safety_set_node;
16121 break;
16122 } else if (scope->id == ScopeIdDecls) {
16123 ScopeDecls *decls_scope = (ScopeDecls *)scope;
16124 safety_off_ptr = &decls_scope->safety_off;
16125 safety_set_node_ptr = &decls_scope->safety_set_node;
16126 break;
16127 } else {
16128 scope = scope->parent;
16129 continue;
16130 }
16131 }
16132 assert(scope != nullptr);
16133
16134 Stage1AirInst *safety_on_value = set_runtime_safety_instruction->safety_on->child;
16135 bool want_runtime_safety;
16136 if (!ir_resolve_bool(ira, safety_on_value, &want_runtime_safety))
16137 return ira->codegen->invalid_inst_gen;
16138
16139 AstNode *source_node = set_runtime_safety_instruction->base.source_node;
16140 if (*safety_set_node_ptr) {
16141 ErrorMsg *msg = ir_add_error_node(ira, source_node,
16142 buf_sprintf("runtime safety set twice for same scope"));
16143 add_error_note(ira->codegen, msg, *safety_set_node_ptr, buf_sprintf("first set here"));
16144 return ira->codegen->invalid_inst_gen;
16145 }
16146 *safety_set_node_ptr = source_node;
16147 *safety_off_ptr = !want_runtime_safety;
16148
16149 return ir_const_void(ira, set_runtime_safety_instruction->base.scope,
16150 set_runtime_safety_instruction->base.source_node);
16151}
16152
16153static Stage1AirInst *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,
16154 Stage1ZirInstSetFloatMode *instruction)
16155{
16156 if (ira->new_irb.exec->is_inline) {
16157 // ignore setFloatMode when running functions at compile time
16158 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
16159 }
16160
16161 bool *fast_math_on_ptr;
16162 AstNode **fast_math_set_node_ptr;
16163
16164 Scope *scope = instruction->base.scope;
16165 while (scope != nullptr) {
16166 if (scope->id == ScopeIdBlock) {
16167 ScopeBlock *block_scope = (ScopeBlock *)scope;
16168 fast_math_on_ptr = &block_scope->fast_math_on;
16169 fast_math_set_node_ptr = &block_scope->fast_math_set_node;
16170 break;
16171 } else if (scope->id == ScopeIdFnDef) {
16172 ScopeFnDef *def_scope = (ScopeFnDef *)scope;
16173 ZigFn *target_fn = def_scope->fn_entry;
16174 assert(target_fn->def_scope != nullptr);
16175 fast_math_on_ptr = &target_fn->def_scope->fast_math_on;
16176 fast_math_set_node_ptr = &target_fn->def_scope->fast_math_set_node;
16177 break;
16178 } else if (scope->id == ScopeIdDecls) {
16179 ScopeDecls *decls_scope = (ScopeDecls *)scope;
16180 fast_math_on_ptr = &decls_scope->fast_math_on;
16181 fast_math_set_node_ptr = &decls_scope->fast_math_set_node;
16182 break;
16183 } else {
16184 scope = scope->parent;
16185 continue;
16186 }
16187 }
16188 assert(scope != nullptr);
16189
16190 Stage1AirInst *float_mode_value = instruction->mode_value->child;
16191 FloatMode float_mode_scalar;
16192 if (!ir_resolve_float_mode(ira, float_mode_value, &float_mode_scalar))
16193 return ira->codegen->invalid_inst_gen;
16194
16195 AstNode *source_node = instruction->base.source_node;
16196 if (*fast_math_set_node_ptr) {
16197 ErrorMsg *msg = ir_add_error_node(ira, source_node,
16198 buf_sprintf("float mode set twice for same scope"));
16199 add_error_note(ira->codegen, msg, *fast_math_set_node_ptr, buf_sprintf("first set here"));
16200 return ira->codegen->invalid_inst_gen;
16201 }
16202 *fast_math_set_node_ptr = source_node;
16203 *fast_math_on_ptr = (float_mode_scalar == FloatModeOptimized);
16204
16205 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
16206}
16207
16208static Stage1AirInst *ir_analyze_instruction_any_frame_type(IrAnalyze *ira, Stage1ZirInstAnyFrameType *instruction) {
16209 ZigType *payload_type = nullptr;
16210 if (instruction->payload_type != nullptr) {
16211 payload_type = ir_resolve_type(ira, instruction->payload_type->child);
16212 if (type_is_invalid(payload_type))
16213 return ira->codegen->invalid_inst_gen;
16214 }
16215
16216 ZigType *any_frame_type = get_any_frame_type(ira->codegen, payload_type);
16217 return ir_const_type(ira, instruction->base.scope, instruction->base.source_node, any_frame_type);
16218}
16219
16220static Stage1AirInst *ir_analyze_instruction_slice_type(IrAnalyze *ira, Stage1ZirInstSliceType *slice_type_instruction) {
16221 Stage1AirInst *result = ir_const(ira, slice_type_instruction->base.scope,
16222 slice_type_instruction->base.source_node, ira->codegen->builtin_types.entry_type);
16223 result->value->special = ConstValSpecialLazy;
16224
16225 LazyValueSliceType *lazy_slice_type = heap::c_allocator.create<LazyValueSliceType>();
16226 lazy_slice_type->ira = ira; ira_ref(ira);
16227 result->value->data.x_lazy = &lazy_slice_type->base;
16228 lazy_slice_type->base.id = LazyValueIdSliceType;
16229
16230 if (slice_type_instruction->align_value != nullptr) {
16231 lazy_slice_type->align_inst = slice_type_instruction->align_value->child;
16232 if (ir_resolve_const(ira, lazy_slice_type->align_inst, LazyOk) == nullptr)
16233 return ira->codegen->invalid_inst_gen;
16234 }
16235
16236 if (slice_type_instruction->sentinel != nullptr) {
16237 lazy_slice_type->sentinel = slice_type_instruction->sentinel->child;
16238 if (ir_resolve_const(ira, lazy_slice_type->sentinel, LazyOk) == nullptr)
16239 return ira->codegen->invalid_inst_gen;
16240 }
16241
16242 lazy_slice_type->elem_type = slice_type_instruction->child_type->child;
16243 if (ir_resolve_type_lazy(ira, lazy_slice_type->elem_type) == nullptr)
16244 return ira->codegen->invalid_inst_gen;
16245
16246 lazy_slice_type->is_const = slice_type_instruction->is_const;
16247 lazy_slice_type->is_volatile = slice_type_instruction->is_volatile;
16248 lazy_slice_type->is_allowzero = slice_type_instruction->is_allow_zero;
16249
16250 return result;
16251}
16252
16253static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_template) {
16254 const char *ptr = buf_ptr(src_template) + tok->start + 2;
16255 size_t len = tok->end - tok->start - 2;
16256 size_t result = 0;
16257 for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) {
16258 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
16259 if (buf_eql_mem(asm_output->asm_symbolic_name, ptr, len)) {
16260 return result;
16261 }
16262 }
16263 for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) {
16264 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
16265 if (buf_eql_mem(asm_input->asm_symbolic_name, ptr, len)) {
16266 return result;
16267 }
16268 }
16269 return SIZE_MAX;
16270}
16271
16272static Stage1AirInst *ir_analyze_instruction_asm(IrAnalyze *ira, Stage1ZirInstAsm *asm_instruction) {
16273 Error err;
16274
16275 assert(asm_instruction->base.source_node->type == NodeTypeAsmExpr);
16276
16277 AstNode *node = asm_instruction->base.source_node;
16278 AstNodeAsmExpr *asm_expr = &asm_instruction->base.source_node->data.asm_expr;
16279
16280 Buf *template_buf = ir_resolve_str(ira, asm_instruction->asm_template->child);
16281 if (template_buf == nullptr)
16282 return ira->codegen->invalid_inst_gen;
16283
16284 if (asm_instruction->is_global) {
16285 buf_append_char(&ira->codegen->global_asm, '\n');
16286 buf_append_buf(&ira->codegen->global_asm, template_buf);
16287
16288 return ir_const_void(ira, asm_instruction->base.scope, asm_instruction->base.source_node);
16289 }
16290
16291 if (!ir_emit_global_runtime_side_effect(ira, &asm_instruction->base))
16292 return ira->codegen->invalid_inst_gen;
16293
16294 ZigList<AsmToken> tok_list = {};
16295 if ((err = parse_asm_template(ira, node, template_buf, &tok_list))) {
16296 return ira->codegen->invalid_inst_gen;
16297 }
16298
16299 for (size_t token_i = 0; token_i < tok_list.length; token_i += 1) {
16300 AsmToken asm_token = tok_list.at(token_i);
16301 if (asm_token.id == AsmTokenIdVar) {
16302 size_t index = find_asm_index(ira->codegen, node, &asm_token, template_buf);
16303 if (index == SIZE_MAX) {
16304 const char *ptr = buf_ptr(template_buf) + asm_token.start + 2;
16305 uint32_t len = asm_token.end - asm_token.start - 2;
16306
16307 add_node_error(ira->codegen, node,
16308 buf_sprintf("could not find '%.*s' in the inputs or outputs",
16309 len, ptr));
16310 return ira->codegen->invalid_inst_gen;
16311 }
16312 }
16313 }
16314
16315 // TODO validate the output types and variable types
16316
16317 Stage1AirInst **input_list = heap::c_allocator.allocate<Stage1AirInst *>(asm_expr->input_list.length);
16318 Stage1AirInst **output_types = heap::c_allocator.allocate<Stage1AirInst *>(asm_expr->output_list.length);
16319
16320 ZigType *return_type = ira->codegen->builtin_types.entry_void;
16321 for (size_t i = 0; i < asm_expr->output_list.length; i += 1) {
16322 AsmOutput *asm_output = asm_expr->output_list.at(i);
16323 if (asm_output->return_type) {
16324 output_types[i] = asm_instruction->output_types[i]->child;
16325 return_type = ir_resolve_type(ira, output_types[i]);
16326 if (type_is_invalid(return_type))
16327 return ira->codegen->invalid_inst_gen;
16328 }
16329 }
16330
16331 for (size_t i = 0; i < asm_expr->input_list.length; i += 1) {
16332 Stage1AirInst *const input_value = asm_instruction->input_list[i]->child;
16333 if (type_is_invalid(input_value->value->type))
16334 return ira->codegen->invalid_inst_gen;
16335
16336 if (instr_is_comptime(input_value) &&
16337 (input_value->value->type->id == ZigTypeIdComptimeInt ||
16338 input_value->value->type->id == ZigTypeIdComptimeFloat)) {
16339 ir_add_error(ira, input_value,
16340 buf_sprintf("expected sized integer or sized float, found %s", buf_ptr(&input_value->value->type->name)));
16341 return ira->codegen->invalid_inst_gen;
16342 }
16343
16344 input_list[i] = input_value;
16345 }
16346
16347 return ir_build_asm_gen(ira, asm_instruction->base.scope, asm_instruction->base.source_node,
16348 template_buf, tok_list.items, tok_list.length,
16349 input_list, output_types, asm_instruction->output_vars, asm_instruction->return_count,
16350 asm_instruction->has_side_effects, return_type);
16351}
16352
16353static Stage1AirInst *ir_analyze_instruction_array_type(IrAnalyze *ira, Stage1ZirInstArrayType *array_type_instruction) {
16354 Stage1AirInst *result = ir_const(ira, array_type_instruction->base.scope,
16355 array_type_instruction->base.source_node, ira->codegen->builtin_types.entry_type);
16356 result->value->special = ConstValSpecialLazy;
16357
16358 LazyValueArrayType *lazy_array_type = heap::c_allocator.create<LazyValueArrayType>();
16359 lazy_array_type->ira = ira; ira_ref(ira);
16360 result->value->data.x_lazy = &lazy_array_type->base;
16361 lazy_array_type->base.id = LazyValueIdArrayType;
16362
16363 lazy_array_type->elem_type = array_type_instruction->child_type->child;
16364 if (ir_resolve_type_lazy(ira, lazy_array_type->elem_type) == nullptr)
16365 return ira->codegen->invalid_inst_gen;
16366
16367 if (!ir_resolve_usize(ira, array_type_instruction->size->child, &lazy_array_type->length))
16368 return ira->codegen->invalid_inst_gen;
16369
16370 if (array_type_instruction->sentinel != nullptr) {
16371 lazy_array_type->sentinel = array_type_instruction->sentinel->child;
16372 if (ir_resolve_const(ira, lazy_array_type->sentinel, LazyOk) == nullptr)
16373 return ira->codegen->invalid_inst_gen;
16374 }
16375
16376 return result;
16377}
16378
16379static Stage1AirInst *ir_analyze_instruction_size_of(IrAnalyze *ira, Stage1ZirInstSizeOf *instruction) {
16380 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int);
16381 result->value->special = ConstValSpecialLazy;
16382
16383 LazyValueSizeOf *lazy_size_of = heap::c_allocator.create<LazyValueSizeOf>();
16384 lazy_size_of->ira = ira; ira_ref(ira);
16385 result->value->data.x_lazy = &lazy_size_of->base;
16386 lazy_size_of->base.id = LazyValueIdSizeOf;
16387 lazy_size_of->bit_size = instruction->bit_size;
16388
16389 lazy_size_of->target_type = instruction->type_value->child;
16390 if (ir_resolve_type_lazy(ira, lazy_size_of->target_type) == nullptr)
16391 return ira->codegen->invalid_inst_gen;
16392
16393 return result;
16394}
16395
16396static Stage1AirInst *ir_analyze_test_non_null(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value) {
16397 ZigType *type_entry = value->value->type;
16398
16399 if (type_entry->id == ZigTypeIdPointer && type_entry->data.pointer.allow_zero) {
16400 if (instr_is_comptime(value)) {
16401 ZigValue *c_ptr_val = ir_resolve_const(ira, value, UndefOk);
16402 if (c_ptr_val == nullptr)
16403 return ira->codegen->invalid_inst_gen;
16404 if (c_ptr_val->special == ConstValSpecialUndef)
16405 return ir_const_undef(ira, scope, source_node, ira->codegen->builtin_types.entry_bool);
16406 bool is_null = c_ptr_val->data.x_ptr.special == ConstPtrSpecialNull ||
16407 (c_ptr_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
16408 c_ptr_val->data.x_ptr.data.hard_coded_addr.addr == 0);
16409 return ir_const_bool(ira, scope, source_node, !is_null);
16410 }
16411
16412 return ir_build_test_non_null_gen(ira, scope, source_node, value);
16413 } else if (type_entry->id == ZigTypeIdOptional) {
16414 if (instr_is_comptime(value)) {
16415 ZigValue *maybe_val = ir_resolve_const(ira, value, UndefOk);
16416 if (maybe_val == nullptr)
16417 return ira->codegen->invalid_inst_gen;
16418 if (maybe_val->special == ConstValSpecialUndef)
16419 return ir_const_undef(ira, scope, source_node, ira->codegen->builtin_types.entry_bool);
16420
16421 return ir_const_bool(ira, scope, source_node, !optional_value_is_null(maybe_val));
16422 }
16423
16424 return ir_build_test_non_null_gen(ira, scope, source_node, value);
16425 } else if (type_entry->id == ZigTypeIdNull) {
16426 return ir_const_bool(ira, scope, source_node, false);
16427 } else {
16428 return ir_const_bool(ira, scope, source_node, true);
16429 }
16430}
16431
16432static Stage1AirInst *ir_analyze_instruction_test_non_null(IrAnalyze *ira, Stage1ZirInstTestNonNull *instruction) {
16433 Stage1AirInst *value = instruction->value->child;
16434 if (type_is_invalid(value->value->type))
16435 return ira->codegen->invalid_inst_gen;
16436
16437 return ir_analyze_test_non_null(ira, instruction->base.scope, instruction->base.source_node, value);
16438}
16439
16440static Stage1AirInst *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, Scope *scope, AstNode *source_node,
16441 Stage1AirInst *base_ptr, bool safety_check_on, bool initializing)
16442{
16443 Error err;
16444
16445 ZigType *type_entry = get_ptr_elem_type(ira->codegen, base_ptr);
16446 if (type_is_invalid(type_entry))
16447 return ira->codegen->invalid_inst_gen;
16448
16449 if (type_entry->id == ZigTypeIdPointer && type_entry->data.pointer.ptr_len == PtrLenC) {
16450 if (instr_is_comptime(base_ptr)) {
16451 ZigValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
16452 if (!val)
16453 return ira->codegen->invalid_inst_gen;
16454 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
16455 ZigValue *c_ptr_val = const_ptr_pointee(ira, ira->codegen, val, source_node);
16456 if (c_ptr_val == nullptr)
16457 return ira->codegen->invalid_inst_gen;
16458 bool is_null = c_ptr_val->data.x_ptr.special == ConstPtrSpecialNull ||
16459 (c_ptr_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
16460 c_ptr_val->data.x_ptr.data.hard_coded_addr.addr == 0);
16461 if (is_null) {
16462 ir_add_error_node(ira, source_node, buf_sprintf("unable to unwrap null"));
16463 return ira->codegen->invalid_inst_gen;
16464 }
16465 return base_ptr;
16466 }
16467 }
16468 if (!safety_check_on)
16469 return base_ptr;
16470 Stage1AirInst *c_ptr_val = ir_get_deref(ira, scope, source_node, base_ptr, nullptr);
16471 ir_build_assert_non_null(ira, scope, source_node, c_ptr_val);
16472 return base_ptr;
16473 }
16474
16475 if (type_entry->id != ZigTypeIdOptional) {
16476 ir_add_error(ira, base_ptr,
16477 buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));
16478 return ira->codegen->invalid_inst_gen;
16479 }
16480
16481 ZigType *child_type = type_entry->data.maybe.child_type;
16482 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
16483 base_ptr->value->type->data.pointer.is_const, base_ptr->value->type->data.pointer.is_volatile,
16484 PtrLenSingle, 0, 0, 0, false);
16485
16486 bool same_comptime_repr = types_have_same_zig_comptime_repr(ira->codegen, child_type, type_entry);
16487
16488 if (instr_is_comptime(base_ptr)) {
16489 ZigValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
16490 if (ptr_val == nullptr)
16491 return ira->codegen->invalid_inst_gen;
16492 if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
16493 ZigValue *optional_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_node);
16494 if (optional_val == nullptr)
16495 return ira->codegen->invalid_inst_gen;
16496
16497 if (initializing) {
16498 switch (type_has_one_possible_value(ira->codegen, child_type)) {
16499 case OnePossibleValueInvalid:
16500 return ira->codegen->invalid_inst_gen;
16501 case OnePossibleValueNo:
16502 if (!same_comptime_repr) {
16503 ZigValue *payload_val = ira->codegen->pass1_arena->create<ZigValue>();
16504 payload_val->type = child_type;
16505 payload_val->special = ConstValSpecialUndef;
16506 payload_val->parent.id = ConstParentIdOptionalPayload;
16507 payload_val->parent.data.p_optional_payload.optional_val = optional_val;
16508
16509 optional_val->data.x_optional = payload_val;
16510 optional_val->special = ConstValSpecialStatic;
16511 }
16512 break;
16513 case OnePossibleValueYes: {
16514 optional_val->special = ConstValSpecialStatic;
16515 optional_val->data.x_optional = get_the_one_possible_value(ira->codegen, child_type);
16516 break;
16517 }
16518 }
16519 } else {
16520 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec,
16521 source_node, optional_val, UndefBad)))
16522 return ira->codegen->invalid_inst_gen;
16523 if (optional_value_is_null(optional_val)) {
16524 ir_add_error_node(ira, source_node, buf_sprintf("unable to unwrap null"));
16525 return ira->codegen->invalid_inst_gen;
16526 }
16527 }
16528
16529 Stage1AirInst *result;
16530 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
16531 result = ir_build_optional_unwrap_ptr_gen(ira, scope, source_node, base_ptr, false,
16532 initializing, result_type);
16533 result->value->special = ConstValSpecialStatic;
16534 } else {
16535 result = ir_const(ira, scope, source_node, result_type);
16536 }
16537 ZigValue *result_val = result->value;
16538 result_val->data.x_ptr.special = ConstPtrSpecialRef;
16539 result_val->data.x_ptr.mut = ptr_val->data.x_ptr.mut;
16540 switch (type_has_one_possible_value(ira->codegen, child_type)) {
16541 case OnePossibleValueInvalid:
16542 return ira->codegen->invalid_inst_gen;
16543 case OnePossibleValueNo:
16544 if (same_comptime_repr) {
16545 result_val->data.x_ptr.data.ref.pointee = optional_val;
16546 } else {
16547 assert(optional_val->data.x_optional != nullptr);
16548 result_val->data.x_ptr.data.ref.pointee = optional_val->data.x_optional;
16549 }
16550 break;
16551 case OnePossibleValueYes:
16552 assert(optional_val->data.x_optional != nullptr);
16553 result_val->data.x_ptr.data.ref.pointee = optional_val->data.x_optional;
16554 break;
16555 }
16556 return result;
16557 }
16558 }
16559
16560 return ir_build_optional_unwrap_ptr_gen(ira, scope, source_node, base_ptr, safety_check_on,
16561 initializing, result_type);
16562}
16563
16564static Stage1AirInst *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira,
16565 Stage1ZirInstOptionalUnwrapPtr *instruction)
16566{
16567 Stage1AirInst *base_ptr = instruction->base_ptr->child;
16568 if (type_is_invalid(base_ptr->value->type))
16569 return ira->codegen->invalid_inst_gen;
16570
16571 return ir_analyze_unwrap_optional_payload(ira, instruction->base.scope, instruction->base.source_node, base_ptr,
16572 instruction->safety_check_on, false);
16573}
16574
16575static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCtz *instruction) {
16576 Error err;
16577
16578 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
16579 if (type_is_invalid(int_type))
16580 return ira->codegen->invalid_inst_gen;
16581
16582 Stage1AirInst *uncasted_op = instruction->op->child;
16583 if (type_is_invalid(uncasted_op->value->type))
16584 return ira->codegen->invalid_inst_gen;
16585
16586 uint32_t vector_len = UINT32_MAX; // means not a vector
16587 if (uncasted_op->value->type->id == ZigTypeIdArray) {
16588 bool can_be_vec_elem;
16589 if ((err = is_valid_vector_elem_type(ira->codegen, uncasted_op->value->type->data.array.child_type,
16590 &can_be_vec_elem)))
16591 {
16592 return ira->codegen->invalid_inst_gen;
16593 }
16594 if (can_be_vec_elem) {
16595 vector_len = uncasted_op->value->type->data.array.len;
16596 }
16597 } else if (uncasted_op->value->type->id == ZigTypeIdVector) {
16598 vector_len = uncasted_op->value->type->data.vector.len;
16599 }
16600
16601 bool is_vector = (vector_len != UINT32_MAX);
16602 ZigType *op_type = is_vector ? get_vector_type(ira->codegen, vector_len, int_type) : int_type;
16603
16604 Stage1AirInst *op = ir_implicit_cast(ira, uncasted_op, op_type);
16605 if (type_is_invalid(op->value->type))
16606 return ira->codegen->invalid_inst_gen;
16607
16608 if (int_type->data.integral.bit_count == 0)
16609 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, 0);
16610
16611 ZigType *smallest_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count);
16612
16613 if (instr_is_comptime(op)) {
16614 ZigValue *val = ir_resolve_const(ira, op, UndefOk);
16615 if (val == nullptr)
16616 return ira->codegen->invalid_inst_gen;
16617 if (val->special == ConstValSpecialUndef)
16618 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int);
16619
16620 if (is_vector) {
16621 ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type);
16622 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type);
16623 expand_undef_array(ira->codegen, val);
16624 result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(smallest_vec_type->data.vector.len);
16625 for (unsigned i = 0; i < smallest_vec_type->data.vector.len; i += 1) {
16626 ZigValue *op_elem_val = &val->data.x_array.data.s_none.elements[i];
16627 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.source_node,
16628 op_elem_val, UndefOk)))
16629 {
16630 return ira->codegen->invalid_inst_gen;
16631 }
16632 ZigValue *result_elem_val = &result->value->data.x_array.data.s_none.elements[i];
16633 result_elem_val->type = smallest_type;
16634 result_elem_val->special = op_elem_val->special;
16635 if (op_elem_val->special == ConstValSpecialUndef)
16636 continue;
16637 size_t value = bigint_ctz(&op_elem_val->data.x_bigint, int_type->data.integral.bit_count);
16638 bigint_init_unsigned(&result->value->data.x_array.data.s_none.elements[i].data.x_bigint, value);
16639 }
16640 return result;
16641 } else {
16642 size_t result_usize = bigint_ctz(&op->value->data.x_bigint, int_type->data.integral.bit_count);
16643 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, result_usize);
16644 }
16645 }
16646
16647 ZigType *return_type = is_vector ? get_vector_type(ira->codegen, vector_len, smallest_type) : smallest_type;
16648 return ir_build_ctz_gen(ira, instruction->base.scope, instruction->base.source_node, return_type, op);
16649}
16650
16651static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstClz *instruction) {
16652 Error err;
16653
16654 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
16655 if (type_is_invalid(int_type))
16656 return ira->codegen->invalid_inst_gen;
16657
16658 Stage1AirInst *uncasted_op = instruction->op->child;
16659 if (type_is_invalid(uncasted_op->value->type))
16660 return ira->codegen->invalid_inst_gen;
16661
16662 uint32_t vector_len = UINT32_MAX; // means not a vector
16663 if (uncasted_op->value->type->id == ZigTypeIdArray) {
16664 bool can_be_vec_elem;
16665 if ((err = is_valid_vector_elem_type(ira->codegen, uncasted_op->value->type->data.array.child_type,
16666 &can_be_vec_elem)))
16667 {
16668 return ira->codegen->invalid_inst_gen;
16669 }
16670 if (can_be_vec_elem) {
16671 vector_len = uncasted_op->value->type->data.array.len;
16672 }
16673 } else if (uncasted_op->value->type->id == ZigTypeIdVector) {
16674 vector_len = uncasted_op->value->type->data.vector.len;
16675 }
16676
16677 bool is_vector = (vector_len != UINT32_MAX);
16678 ZigType *op_type = is_vector ? get_vector_type(ira->codegen, vector_len, int_type) : int_type;
16679
16680 Stage1AirInst *op = ir_implicit_cast(ira, uncasted_op, op_type);
16681 if (type_is_invalid(op->value->type))
16682 return ira->codegen->invalid_inst_gen;
16683
16684 if (int_type->data.integral.bit_count == 0)
16685 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, 0);
16686
16687 ZigType *smallest_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count);
16688
16689 if (instr_is_comptime(op)) {
16690 ZigValue *val = ir_resolve_const(ira, op, UndefOk);
16691 if (val == nullptr)
16692 return ira->codegen->invalid_inst_gen;
16693 if (val->special == ConstValSpecialUndef)
16694 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int);
16695
16696 if (is_vector) {
16697 ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type);
16698 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type);
16699 expand_undef_array(ira->codegen, val);
16700 result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(smallest_vec_type->data.vector.len);
16701 for (unsigned i = 0; i < smallest_vec_type->data.vector.len; i += 1) {
16702 ZigValue *op_elem_val = &val->data.x_array.data.s_none.elements[i];
16703 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.source_node,
16704 op_elem_val, UndefOk)))
16705 {
16706 return ira->codegen->invalid_inst_gen;
16707 }
16708 ZigValue *result_elem_val = &result->value->data.x_array.data.s_none.elements[i];
16709 result_elem_val->type = smallest_type;
16710 result_elem_val->special = op_elem_val->special;
16711 if (op_elem_val->special == ConstValSpecialUndef)
16712 continue;
16713 size_t value = bigint_clz(&op_elem_val->data.x_bigint, int_type->data.integral.bit_count);
16714 bigint_init_unsigned(&result->value->data.x_array.data.s_none.elements[i].data.x_bigint, value);
16715 }
16716 return result;
16717 } else {
16718 size_t result_usize = bigint_clz(&op->value->data.x_bigint, int_type->data.integral.bit_count);
16719 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, result_usize);
16720 }
16721 }
16722
16723 ZigType *return_type = is_vector ? get_vector_type(ira->codegen, vector_len, smallest_type) : smallest_type;
16724 return ir_build_clz_gen(ira, instruction->base.scope, instruction->base.source_node, return_type, op);
16725}
16726
16727static Stage1AirInst *ir_analyze_instruction_pop_count(IrAnalyze *ira, Stage1ZirInstPopCount *instruction) {
16728 Error err;
16729
16730 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
16731 if (type_is_invalid(int_type))
16732 return ira->codegen->invalid_inst_gen;
16733
16734 Stage1AirInst *uncasted_op = instruction->op->child;
16735 if (type_is_invalid(uncasted_op->value->type))
16736 return ira->codegen->invalid_inst_gen;
16737
16738 uint32_t vector_len = UINT32_MAX; // means not a vector
16739 if (uncasted_op->value->type->id == ZigTypeIdArray) {
16740 bool can_be_vec_elem;
16741 if ((err = is_valid_vector_elem_type(ira->codegen, uncasted_op->value->type->data.array.child_type,
16742 &can_be_vec_elem)))
16743 {
16744 return ira->codegen->invalid_inst_gen;
16745 }
16746 if (can_be_vec_elem) {
16747 vector_len = uncasted_op->value->type->data.array.len;
16748 }
16749 } else if (uncasted_op->value->type->id == ZigTypeIdVector) {
16750 vector_len = uncasted_op->value->type->data.vector.len;
16751 }
16752
16753 bool is_vector = (vector_len != UINT32_MAX);
16754 ZigType *op_type = is_vector ? get_vector_type(ira->codegen, vector_len, int_type) : int_type;
16755
16756 Stage1AirInst *op = ir_implicit_cast(ira, uncasted_op, op_type);
16757 if (type_is_invalid(op->value->type))
16758 return ira->codegen->invalid_inst_gen;
16759
16760 if (int_type->data.integral.bit_count == 0)
16761 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, 0);
16762
16763 ZigType *smallest_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count);
16764
16765 if (instr_is_comptime(op)) {
16766 ZigValue *val = ir_resolve_const(ira, op, UndefOk);
16767 if (val == nullptr)
16768 return ira->codegen->invalid_inst_gen;
16769 if (val->special == ConstValSpecialUndef)
16770 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int);
16771
16772 if (is_vector) {
16773 ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type);
16774 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type);
16775 expand_undef_array(ira->codegen, val);
16776 result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(smallest_vec_type->data.vector.len);
16777 for (unsigned i = 0; i < smallest_vec_type->data.vector.len; i += 1) {
16778 ZigValue *op_elem_val = &val->data.x_array.data.s_none.elements[i];
16779 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.source_node,
16780 op_elem_val, UndefOk)))
16781 {
16782 return ira->codegen->invalid_inst_gen;
16783 }
16784 ZigValue *result_elem_val = &result->value->data.x_array.data.s_none.elements[i];
16785 result_elem_val->type = smallest_type;
16786 result_elem_val->special = op_elem_val->special;
16787 if (op_elem_val->special == ConstValSpecialUndef)
16788 continue;
16789
16790 if (bigint_cmp_zero(&op_elem_val->data.x_bigint) != CmpLT) {
16791 size_t value = bigint_popcount_unsigned(&op_elem_val->data.x_bigint);
16792 bigint_init_unsigned(&result->value->data.x_array.data.s_none.elements[i].data.x_bigint, value);
16793 }
16794 size_t value = bigint_popcount_signed(&op_elem_val->data.x_bigint, int_type->data.integral.bit_count);
16795 bigint_init_unsigned(&result->value->data.x_array.data.s_none.elements[i].data.x_bigint, value);
16796 }
16797 return result;
16798 } else {
16799 if (bigint_cmp_zero(&val->data.x_bigint) != CmpLT) {
16800 size_t result = bigint_popcount_unsigned(&val->data.x_bigint);
16801 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, result);
16802 }
16803 size_t result = bigint_popcount_signed(&val->data.x_bigint, int_type->data.integral.bit_count);
16804 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, result);
16805 }
16806 }
16807
16808 ZigType *return_type = is_vector ? get_vector_type(ira->codegen, vector_len, smallest_type) : smallest_type;
16809 return ir_build_pop_count_gen(ira, instruction->base.scope, instruction->base.source_node, return_type, op);
16810}
16811
16812static Stage1AirInst *ir_analyze_union_tag(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value) {
16813 if (type_is_invalid(value->value->type))
16814 return ira->codegen->invalid_inst_gen;
16815
16816 if (value->value->type->id != ZigTypeIdUnion) {
16817 ir_add_error(ira, value,
16818 buf_sprintf("expected enum or union type, found '%s'", buf_ptr(&value->value->type->name)));
16819 return ira->codegen->invalid_inst_gen;
16820 }
16821 if (!value->value->type->data.unionation.have_explicit_tag_type) {
16822 ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("union has no associated enum"));
16823 if (value->value->type->data.unionation.decl_node != nullptr) {
16824 add_error_note(ira->codegen, msg, value->value->type->data.unionation.decl_node,
16825 buf_sprintf("declared here"));
16826 }
16827 return ira->codegen->invalid_inst_gen;
16828 }
16829
16830 ZigType *tag_type = value->value->type->data.unionation.tag_type;
16831 assert(tag_type->id == ZigTypeIdEnum);
16832
16833 if (instr_is_comptime(value)) {
16834 ZigValue *val = ir_resolve_const(ira, value, UndefBad);
16835 if (!val)
16836 return ira->codegen->invalid_inst_gen;
16837
16838 Stage1AirInstConst *const_instruction = ir_create_inst_gen<Stage1AirInstConst>(&ira->new_irb,
16839 scope, source_node);
16840 const_instruction->base.value->type = tag_type;
16841 const_instruction->base.value->special = ConstValSpecialStatic;
16842 bigint_init_bigint(&const_instruction->base.value->data.x_enum_tag, &val->data.x_union.tag);
16843 return &const_instruction->base;
16844 }
16845
16846 return ir_build_union_tag(ira, scope, source_node, value, tag_type);
16847}
16848
16849static Stage1AirInst *ir_analyze_instruction_switch_br(IrAnalyze *ira,
16850 Stage1ZirInstSwitchBr *switch_br_instruction)
16851{
16852 Stage1AirInst *target_value = switch_br_instruction->target_value->child;
16853 if (type_is_invalid(target_value->value->type))
16854 return ir_unreach_error(ira);
16855
16856 if (switch_br_instruction->switch_prongs_void != nullptr) {
16857 if (type_is_invalid(switch_br_instruction->switch_prongs_void->child->value->type)) {
16858 return ir_unreach_error(ira);
16859 }
16860 }
16861
16862
16863 size_t case_count = switch_br_instruction->case_count;
16864
16865 bool is_comptime;
16866 if (!ir_resolve_comptime(ira, switch_br_instruction->is_comptime->child, &is_comptime))
16867 return ira->codegen->invalid_inst_gen;
16868
16869 if (is_comptime || instr_is_comptime(target_value)) {
16870 ZigValue *target_val = ir_resolve_const(ira, target_value, UndefBad);
16871 if (!target_val)
16872 return ir_unreach_error(ira);
16873
16874 Stage1ZirBasicBlock *old_dest_block = switch_br_instruction->else_block;
16875 for (size_t i = 0; i < case_count; i += 1) {
16876 Stage1ZirInstSwitchBrCase *old_case = &switch_br_instruction->cases[i];
16877 Stage1AirInst *case_value = old_case->value->child;
16878 if (type_is_invalid(case_value->value->type))
16879 return ir_unreach_error(ira);
16880
16881 Stage1AirInst *casted_case_value = ir_implicit_cast(ira, case_value, target_value->value->type);
16882 if (type_is_invalid(casted_case_value->value->type))
16883 return ir_unreach_error(ira);
16884
16885 ZigValue *case_val = ir_resolve_const(ira, casted_case_value, UndefBad);
16886 if (!case_val)
16887 return ir_unreach_error(ira);
16888
16889 if (const_values_equal(ira->codegen, target_val, case_val)) {
16890 old_dest_block = old_case->block;
16891 break;
16892 }
16893 }
16894
16895 if (is_comptime || old_dest_block->ref_count == 1) {
16896 return ir_inline_bb(ira, switch_br_instruction->base.source_node, old_dest_block);
16897 } else {
16898 Stage1AirBasicBlock *new_dest_block = ir_get_new_bb(ira, old_dest_block, &switch_br_instruction->base);
16899 Stage1AirInst *result = ir_build_br_gen(ira, switch_br_instruction->base.scope,
16900 switch_br_instruction->base.source_node, new_dest_block);
16901 return ir_finish_anal(ira, result);
16902 }
16903 }
16904
16905 Stage1AirInstSwitchBrCase *cases = heap::c_allocator.allocate<Stage1AirInstSwitchBrCase>(case_count);
16906 for (size_t i = 0; i < case_count; i += 1) {
16907 Stage1ZirInstSwitchBrCase *old_case = &switch_br_instruction->cases[i];
16908 Stage1AirInstSwitchBrCase *new_case = &cases[i];
16909 new_case->block = ir_get_new_bb(ira, old_case->block, &switch_br_instruction->base);
16910 new_case->value = ira->codegen->invalid_inst_gen;
16911
16912 // Calling ir_get_new_bb set the ref_instruction on the new basic block.
16913 // However a switch br may branch to the same basic block which would trigger an
16914 // incorrect re-generation of the block. So we set it to null here and assign
16915 // it back after the loop.
16916 new_case->block->ref_instruction = nullptr;
16917
16918 Stage1ZirInst *old_value = old_case->value;
16919 Stage1AirInst *new_value = old_value->child;
16920 if (type_is_invalid(new_value->value->type))
16921 continue;
16922
16923 Stage1AirInst *casted_new_value = ir_implicit_cast(ira, new_value, target_value->value->type);
16924 if (type_is_invalid(casted_new_value->value->type))
16925 continue;
16926
16927 if (!ir_resolve_const(ira, casted_new_value, UndefBad))
16928 continue;
16929
16930 new_case->value = casted_new_value;
16931 }
16932
16933 for (size_t i = 0; i < case_count; i += 1) {
16934 Stage1AirInstSwitchBrCase *new_case = &cases[i];
16935 if (type_is_invalid(new_case->value->value->type))
16936 return ir_unreach_error(ira);
16937 new_case->block->ref_instruction = &switch_br_instruction->base;
16938 }
16939
16940 Stage1AirBasicBlock *new_else_block = ir_get_new_bb(ira, switch_br_instruction->else_block, &switch_br_instruction->base);
16941 Stage1AirInstSwitchBr *switch_br = ir_build_switch_br_gen(ira, switch_br_instruction->base.scope,
16942 switch_br_instruction->base.source_node, target_value, new_else_block, case_count, cases);
16943 return ir_finish_anal(ira, &switch_br->base);
16944}
16945
16946static Stage1AirInst *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16947 Stage1ZirInstSwitchTarget *switch_target_instruction)
16948{
16949 Error err;
16950 Stage1AirInst *target_value_ptr = switch_target_instruction->target_value_ptr->child;
16951 if (type_is_invalid(target_value_ptr->value->type))
16952 return ira->codegen->invalid_inst_gen;
16953
16954 if (target_value_ptr->value->type->id == ZigTypeIdMetaType) {
16955 assert(instr_is_comptime(target_value_ptr));
16956 ZigType *ptr_type = target_value_ptr->value->data.x_type;
16957 assert(ptr_type->id == ZigTypeIdPointer);
16958 return ir_const_type(ira, switch_target_instruction->base.scope,
16959 switch_target_instruction->base.source_node, ptr_type->data.pointer.child_type);
16960 }
16961
16962 ZigType *target_type = target_value_ptr->value->type->data.pointer.child_type;
16963 ZigValue *pointee_val = nullptr;
16964 if (instr_is_comptime(target_value_ptr) && target_value_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
16965 pointee_val = const_ptr_pointee(ira, ira->codegen, target_value_ptr->value, target_value_ptr->source_node);
16966 if (pointee_val == nullptr)
16967 return ira->codegen->invalid_inst_gen;
16968
16969 if (pointee_val->special == ConstValSpecialRuntime)
16970 pointee_val = nullptr;
16971 }
16972 if ((err = type_resolve(ira->codegen, target_type, ResolveStatusSizeKnown)))
16973 return ira->codegen->invalid_inst_gen;
16974
16975 switch (target_type->id) {
16976 case ZigTypeIdInvalid:
16977 zig_unreachable();
16978 case ZigTypeIdMetaType:
16979 case ZigTypeIdVoid:
16980 case ZigTypeIdBool:
16981 case ZigTypeIdInt:
16982 case ZigTypeIdFloat:
16983 case ZigTypeIdComptimeFloat:
16984 case ZigTypeIdComptimeInt:
16985 case ZigTypeIdEnumLiteral:
16986 case ZigTypeIdPointer:
16987 case ZigTypeIdFn:
16988 case ZigTypeIdErrorSet: {
16989 if (pointee_val) {
16990 Stage1AirInst *result = ir_const(ira, switch_target_instruction->base.scope,
16991 switch_target_instruction->base.source_node, nullptr);
16992 copy_const_val(ira->codegen, result->value, pointee_val);
16993 result->value->type = target_type;
16994 return result;
16995 }
16996
16997 Stage1AirInst *result = ir_get_deref(ira, switch_target_instruction->base.scope,
16998 switch_target_instruction->base.source_node, target_value_ptr, nullptr);
16999 result->value->type = target_type;
17000 return result;
17001 }
17002 case ZigTypeIdUnion: {
17003 AstNode *decl_node = target_type->data.unionation.decl_node;
17004 if (!decl_node->data.container_decl.auto_enum &&
17005 decl_node->data.container_decl.init_arg_expr == nullptr)
17006 {
17007 ErrorMsg *msg = ir_add_error(ira, target_value_ptr,
17008 buf_sprintf("switch on union which has no attached enum"));
17009 add_error_note(ira->codegen, msg, decl_node,
17010 buf_sprintf("consider 'union(enum)' here"));
17011 return ira->codegen->invalid_inst_gen;
17012 }
17013 ZigType *tag_type = target_type->data.unionation.tag_type;
17014 assert(tag_type != nullptr);
17015 assert(tag_type->id == ZigTypeIdEnum);
17016 if (pointee_val) {
17017 Stage1AirInst *result = ir_const(ira, switch_target_instruction->base.scope, switch_target_instruction->base.source_node, tag_type);
17018 bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag);
17019 return result;
17020 }
17021
17022 if (can_fold_enum_type(tag_type)) {
17023 Stage1AirInst *result = ir_const(ira, switch_target_instruction->base.scope, switch_target_instruction->base.source_node, tag_type);
17024 TypeEnumField *only_field = &tag_type->data.enumeration.fields[0];
17025 bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value);
17026 return result;
17027 }
17028
17029 Stage1AirInst *union_value = ir_get_deref(ira, switch_target_instruction->base.scope,
17030 switch_target_instruction->base.source_node, target_value_ptr, nullptr);
17031 union_value->value->type = target_type;
17032
17033 return ir_build_union_tag(ira, switch_target_instruction->base.scope, switch_target_instruction->base.source_node, union_value, tag_type);
17034 }
17035 case ZigTypeIdEnum: {
17036 if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
17037 return ira->codegen->invalid_inst_gen;
17038
17039 if (can_fold_enum_type(target_type)) {
17040 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
17041 Stage1AirInst *result = ir_const(ira, switch_target_instruction->base.scope, switch_target_instruction->base.source_node, target_type);
17042 bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value);
17043 return result;
17044 }
17045
17046 if (pointee_val) {
17047 Stage1AirInst *result = ir_const(ira, switch_target_instruction->base.scope, switch_target_instruction->base.source_node, target_type);
17048 bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_enum_tag);
17049 return result;
17050 }
17051
17052 Stage1AirInst *enum_value = ir_get_deref(ira, switch_target_instruction->base.scope,
17053 switch_target_instruction->base.source_node, target_value_ptr, nullptr);
17054 enum_value->value->type = target_type;
17055 return enum_value;
17056 }
17057 case ZigTypeIdErrorUnion:
17058 case ZigTypeIdUnreachable:
17059 case ZigTypeIdArray:
17060 case ZigTypeIdStruct:
17061 case ZigTypeIdUndefined:
17062 case ZigTypeIdNull:
17063 case ZigTypeIdOptional:
17064 case ZigTypeIdBoundFn:
17065 case ZigTypeIdOpaque:
17066 case ZigTypeIdVector:
17067 case ZigTypeIdFnFrame:
17068 case ZigTypeIdAnyFrame:
17069 ir_add_error_node(ira, switch_target_instruction->base.source_node,
17070 buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
17071 return ira->codegen->invalid_inst_gen;
17072 }
17073 zig_unreachable();
17074}
17075
17076static Stage1AirInst *ir_analyze_instruction_switch_var(IrAnalyze *ira, Stage1ZirInstSwitchVar *instruction) {
17077 Stage1AirInst *target_value_ptr = instruction->target_value_ptr->child;
17078 if (type_is_invalid(target_value_ptr->value->type))
17079 return ira->codegen->invalid_inst_gen;
17080
17081 ZigType *ref_type = target_value_ptr->value->type;
17082 assert(ref_type->id == ZigTypeIdPointer);
17083 ZigType *target_type = target_value_ptr->value->type->data.pointer.child_type;
17084 if (target_type->id == ZigTypeIdUnion) {
17085 ZigType *enum_type = target_type->data.unionation.tag_type;
17086 assert(enum_type != nullptr);
17087 assert(enum_type->id == ZigTypeIdEnum);
17088 assert(instruction->prongs_len > 0);
17089
17090 Stage1AirInst *first_prong_value = instruction->prongs_ptr[0]->child;
17091 if (type_is_invalid(first_prong_value->value->type))
17092 return ira->codegen->invalid_inst_gen;
17093
17094 Stage1AirInst *first_casted_prong_value = ir_implicit_cast(ira, first_prong_value, enum_type);
17095 if (type_is_invalid(first_casted_prong_value->value->type))
17096 return ira->codegen->invalid_inst_gen;
17097
17098 ZigValue *first_prong_val = ir_resolve_const(ira, first_casted_prong_value, UndefBad);
17099 if (first_prong_val == nullptr)
17100 return ira->codegen->invalid_inst_gen;
17101
17102 TypeUnionField *first_field = find_union_field_by_tag(target_type, &first_prong_val->data.x_enum_tag);
17103
17104 ErrorMsg *invalid_payload_msg = nullptr;
17105 for (size_t prong_i = 1; prong_i < instruction->prongs_len; prong_i += 1) {
17106 Stage1AirInst *this_prong_inst = instruction->prongs_ptr[prong_i]->child;
17107 if (type_is_invalid(this_prong_inst->value->type))
17108 return ira->codegen->invalid_inst_gen;
17109
17110 Stage1AirInst *this_casted_prong_value = ir_implicit_cast(ira, this_prong_inst, enum_type);
17111 if (type_is_invalid(this_casted_prong_value->value->type))
17112 return ira->codegen->invalid_inst_gen;
17113
17114 ZigValue *this_prong = ir_resolve_const(ira, this_casted_prong_value, UndefBad);
17115 if (this_prong == nullptr)
17116 return ira->codegen->invalid_inst_gen;
17117
17118 TypeUnionField *payload_field = find_union_field_by_tag(target_type, &this_prong->data.x_enum_tag);
17119 ZigType *payload_type = payload_field->type_entry;
17120 if (first_field->type_entry != payload_type) {
17121 if (invalid_payload_msg == nullptr) {
17122 invalid_payload_msg = ir_add_error_node(ira, instruction->base.source_node,
17123 buf_sprintf("capture group with incompatible types"));
17124 add_error_note(ira->codegen, invalid_payload_msg, first_prong_value->source_node,
17125 buf_sprintf("type '%s' here", buf_ptr(&first_field->type_entry->name)));
17126 }
17127 add_error_note(ira->codegen, invalid_payload_msg, this_prong_inst->source_node,
17128 buf_sprintf("type '%s' here", buf_ptr(&payload_field->type_entry->name)));
17129 }
17130 }
17131
17132 if (invalid_payload_msg != nullptr) {
17133 return ira->codegen->invalid_inst_gen;
17134 }
17135
17136 if (instr_is_comptime(target_value_ptr)) {
17137 ZigValue *target_val_ptr = ir_resolve_const(ira, target_value_ptr, UndefBad);
17138 if (!target_value_ptr)
17139 return ira->codegen->invalid_inst_gen;
17140
17141 ZigValue *pointee_val = const_ptr_pointee(ira, ira->codegen, target_val_ptr, instruction->base.source_node);
17142 if (pointee_val == nullptr)
17143 return ira->codegen->invalid_inst_gen;
17144
17145 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node,
17146 get_pointer_to_type(ira->codegen, first_field->type_entry,
17147 target_val_ptr->type->data.pointer.is_const));
17148 ZigValue *out_val = result->value;
17149 out_val->data.x_ptr.special = ConstPtrSpecialRef;
17150 out_val->data.x_ptr.mut = target_val_ptr->data.x_ptr.mut;
17151 out_val->data.x_ptr.data.ref.pointee = pointee_val->data.x_union.payload;
17152 return result;
17153 }
17154
17155 ZigType *result_type = get_pointer_to_type(ira->codegen, first_field->type_entry,
17156 target_value_ptr->value->type->data.pointer.is_const);
17157 return ir_build_union_field_ptr(ira, instruction->base.scope, instruction->base.source_node, target_value_ptr, first_field,
17158 false, false, result_type);
17159 } else if (target_type->id == ZigTypeIdErrorSet) {
17160 // construct an error set from the prong values
17161 ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
17162 err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits;
17163 err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align;
17164 err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size;
17165 ZigList<ErrorTableEntry *> error_list = {};
17166 buf_resize(&err_set_type->name, 0);
17167 buf_appendf(&err_set_type->name, "error{");
17168 for (size_t i = 0; i < instruction->prongs_len; i += 1) {
17169 ErrorTableEntry *err = ir_resolve_error(ira, instruction->prongs_ptr[i]->child);
17170 if (err == nullptr)
17171 return ira->codegen->invalid_inst_gen;
17172 error_list.append(err);
17173 buf_appendf(&err_set_type->name, "%s,", buf_ptr(&err->name));
17174 }
17175 err_set_type->data.error_set.errors = error_list.items;
17176 err_set_type->data.error_set.err_count = error_list.length;
17177 buf_appendf(&err_set_type->name, "}");
17178
17179
17180 ZigType *new_target_value_ptr_type = get_pointer_to_type_extra(ira->codegen,
17181 err_set_type,
17182 ref_type->data.pointer.is_const, ref_type->data.pointer.is_volatile,
17183 ref_type->data.pointer.ptr_len,
17184 ref_type->data.pointer.explicit_alignment,
17185 ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes,
17186 ref_type->data.pointer.allow_zero);
17187 return ir_analyze_ptr_cast(ira, instruction->base.scope, instruction->base.source_node,
17188 target_value_ptr, instruction->target_value_ptr->source_node,
17189 new_target_value_ptr_type, instruction->base.source_node, false, false);
17190 } else if (instruction->prongs_len > 1) {
17191 return target_value_ptr;
17192 } else {
17193 ir_add_error_node(ira, instruction->base.source_node,
17194 buf_sprintf("switch on type '%s' provides no expression parameter", buf_ptr(&target_type->name)));
17195 return ira->codegen->invalid_inst_gen;
17196 }
17197}
17198
17199static Stage1AirInst *ir_analyze_instruction_switch_else_var(IrAnalyze *ira,
17200 Stage1ZirInstSwitchElseVar *instruction)
17201{
17202 Stage1AirInst *target_value_ptr = instruction->target_value_ptr->child;
17203 if (type_is_invalid(target_value_ptr->value->type))
17204 return ira->codegen->invalid_inst_gen;
17205
17206 ZigType *ref_type = target_value_ptr->value->type;
17207 assert(ref_type->id == ZigTypeIdPointer);
17208 ZigType *target_type = target_value_ptr->value->type->data.pointer.child_type;
17209 if (target_type->id == ZigTypeIdErrorSet) {
17210 // make a new set that has the other cases removed
17211 if (!resolve_inferred_error_set(ira->codegen, target_type, instruction->base.source_node)) {
17212 return ira->codegen->invalid_inst_gen;
17213 }
17214 if (type_is_global_error_set(target_type)) {
17215 // the type of the else capture variable still has to be the global error set.
17216 // once the runtime hint system is more sophisticated, we could add some hint information here.
17217 return target_value_ptr;
17218 }
17219 // Make note of the errors handled by other cases
17220 ErrorTableEntry **errors = heap::c_allocator.allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length);
17221 // We may not have any case in the switch if this is a lone else
17222 const size_t switch_cases = instruction->switch_br ? instruction->switch_br->case_count : 0;
17223 for (size_t case_i = 0; case_i < switch_cases; case_i += 1) {
17224 Stage1ZirInstSwitchBrCase *br_case = &instruction->switch_br->cases[case_i];
17225 Stage1AirInst *case_expr = br_case->value->child;
17226 if (case_expr->value->type->id == ZigTypeIdErrorSet) {
17227 ErrorTableEntry *err = ir_resolve_error(ira, case_expr);
17228 if (err == nullptr)
17229 return ira->codegen->invalid_inst_gen;
17230 errors[err->value] = err;
17231 } else if (case_expr->value->type->id == ZigTypeIdMetaType) {
17232 ZigType *err_set_type = ir_resolve_type(ira, case_expr);
17233 if (type_is_invalid(err_set_type))
17234 return ira->codegen->invalid_inst_gen;
17235 populate_error_set_table(errors, err_set_type);
17236 } else {
17237 zig_unreachable();
17238 }
17239 }
17240 ZigList<ErrorTableEntry *> result_list = {};
17241
17242 ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
17243 buf_resize(&err_set_type->name, 0);
17244 buf_appendf(&err_set_type->name, "error{");
17245
17246 // Look at all the errors in the type switched on and add them to the result_list
17247 // if they are not handled by cases.
17248 for (uint32_t i = 0; i < target_type->data.error_set.err_count; i += 1) {
17249 ErrorTableEntry *error_entry = target_type->data.error_set.errors[i];
17250 ErrorTableEntry *existing_entry = errors[error_entry->value];
17251 if (existing_entry == nullptr) {
17252 result_list.append(error_entry);
17253 buf_appendf(&err_set_type->name, "%s,", buf_ptr(&error_entry->name));
17254 }
17255 }
17256 heap::c_allocator.deallocate(errors, ira->codegen->errors_by_index.length);
17257
17258 err_set_type->data.error_set.err_count = result_list.length;
17259 err_set_type->data.error_set.errors = result_list.items;
17260 err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits;
17261 err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align;
17262 err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size;
17263
17264 buf_appendf(&err_set_type->name, "}");
17265
17266 ZigType *new_target_value_ptr_type = get_pointer_to_type_extra(ira->codegen,
17267 err_set_type,
17268 ref_type->data.pointer.is_const, ref_type->data.pointer.is_volatile,
17269 ref_type->data.pointer.ptr_len,
17270 ref_type->data.pointer.explicit_alignment,
17271 ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes,
17272 ref_type->data.pointer.allow_zero);
17273 return ir_analyze_ptr_cast(ira, instruction->base.scope, instruction->base.source_node,
17274 target_value_ptr, instruction->target_value_ptr->source_node,
17275 new_target_value_ptr_type, instruction->base.source_node, false, false);
17276 }
17277
17278 return target_value_ptr;
17279}
17280
17281static Stage1AirInst *ir_analyze_instruction_import(IrAnalyze *ira, Stage1ZirInstImport *import_instruction) {
17282 Error err;
17283
17284 Stage1AirInst *name_value = import_instruction->name->child;
17285 Buf *import_target_str = ir_resolve_str(ira, name_value);
17286 if (!import_target_str)
17287 return ira->codegen->invalid_inst_gen;
17288
17289 AstNode *source_node = import_instruction->base.source_node;
17290 ZigType *import = source_node->owner;
17291
17292 ZigType *target_import;
17293 Buf *import_target_path;
17294 Buf full_path = BUF_INIT;
17295 if ((err = analyze_import(ira->codegen, import, import_target_str, &target_import,
17296 &import_target_path, &full_path)))
17297 {
17298 if (err == ErrorImportOutsidePkgPath) {
17299 ir_add_error_node(ira, source_node,
17300 buf_sprintf("import of file outside package path: '%s'",
17301 buf_ptr(import_target_path)));
17302 return ira->codegen->invalid_inst_gen;
17303 } else if (err == ErrorFileNotFound) {
17304 ir_add_error_node(ira, source_node,
17305 buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
17306 return ira->codegen->invalid_inst_gen;
17307 } else {
17308 ir_add_error_node(ira, source_node,
17309 buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
17310 return ira->codegen->invalid_inst_gen;
17311 }
17312 }
17313
17314 return ir_const_type(ira, import_instruction->base.scope, import_instruction->base.source_node, target_import);
17315}
17316
17317static Stage1AirInst *ir_analyze_instruction_ref(IrAnalyze *ira, Stage1ZirInstRef *ref_instruction) {
17318 Stage1AirInst *value = ref_instruction->value->child;
17319 if (type_is_invalid(value->value->type))
17320 return ira->codegen->invalid_inst_gen;
17321
17322 bool is_const = false;
17323 bool is_volatile = false;
17324
17325 ZigValue *child_value = value->value;
17326 if (child_value->special == ConstValSpecialStatic) {
17327 is_const = true;
17328 }
17329
17330 return ir_get_ref(ira, ref_instruction->base.scope, ref_instruction->base.source_node, value, is_const, is_volatile);
17331}
17332
17333static Stage1AirInst *ir_analyze_union_init(IrAnalyze *ira, Scope *scope, AstNode *source_node,
17334 AstNode *field_source_node, ZigType *union_type, Buf *field_name, Stage1AirInst *field_result_loc,
17335 Stage1AirInst *result_loc)
17336{
17337 Error err;
17338 assert(union_type->id == ZigTypeIdUnion);
17339
17340 if ((err = type_resolve(ira->codegen, union_type, ResolveStatusZeroBitsKnown)))
17341 return ira->codegen->invalid_inst_gen;
17342
17343 TypeUnionField *type_field = find_union_type_field(union_type, field_name);
17344 if (type_field == nullptr) {
17345 ir_add_error_node(ira, field_source_node,
17346 buf_sprintf("no field named '%s' in union '%s'",
17347 buf_ptr(field_name), buf_ptr(&union_type->name)));
17348 return ira->codegen->invalid_inst_gen;
17349 }
17350
17351 if (type_is_invalid(type_field->type_entry))
17352 return ira->codegen->invalid_inst_gen;
17353
17354 if (result_loc->value->data.x_ptr.mut == ConstPtrMutInfer) {
17355 if (instr_is_comptime(field_result_loc) &&
17356 field_result_loc->value->data.x_ptr.mut != ConstPtrMutRuntimeVar)
17357 {
17358 // nothing
17359 } else {
17360 result_loc->value->special = ConstValSpecialRuntime;
17361 }
17362 }
17363
17364 bool is_comptime = ir_should_inline(ira->zir, scope)
17365 || type_requires_comptime(ira->codegen, union_type) == ReqCompTimeYes;
17366
17367 Stage1AirInst *result = ir_get_deref(ira, scope, source_node, result_loc, nullptr);
17368 if (is_comptime && !instr_is_comptime(result)) {
17369 ir_add_error(ira, field_result_loc,
17370 buf_sprintf("unable to evaluate constant expression"));
17371 return ira->codegen->invalid_inst_gen;
17372 }
17373 return result;
17374}
17375
17376static Stage1AirInst *ir_analyze_container_init_fields(IrAnalyze *ira, Scope *scope, AstNode *source_node,
17377 ZigType *container_type, size_t instr_field_count, Stage1ZirInstContainerInitFieldsField *fields,
17378 Stage1AirInst *result_loc)
17379{
17380 Error err;
17381 if (container_type->id == ZigTypeIdUnion) {
17382 if (instr_field_count != 1) {
17383 ir_add_error_node(ira, source_node,
17384 buf_sprintf("union initialization expects exactly one field"));
17385 return ira->codegen->invalid_inst_gen;
17386 }
17387 Stage1ZirInstContainerInitFieldsField *field = &fields[0];
17388 Stage1AirInst *field_result_loc = field->result_loc->child;
17389 if (type_is_invalid(field_result_loc->value->type))
17390 return ira->codegen->invalid_inst_gen;
17391
17392 return ir_analyze_union_init(ira, scope, source_node, field->source_node, container_type, field->name,
17393 field_result_loc, result_loc);
17394 }
17395 if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) {
17396 ir_add_error_node(ira, source_node,
17397 buf_sprintf("type '%s' does not support struct initialization syntax",
17398 buf_ptr(&container_type->name)));
17399 return ira->codegen->invalid_inst_gen;
17400 }
17401
17402 if (container_type->data.structure.resolve_status == ResolveStatusBeingInferred) {
17403 // We're now done inferring the type.
17404 container_type->data.structure.resolve_status = ResolveStatusUnstarted;
17405 }
17406
17407 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
17408 return ira->codegen->invalid_inst_gen;
17409
17410 size_t actual_field_count = container_type->data.structure.src_field_count;
17411
17412 Stage1AirInst *first_non_const_instruction = nullptr;
17413
17414 AstNode **field_assign_nodes = heap::c_allocator.allocate<AstNode *>(actual_field_count);
17415 ZigList<Stage1AirInst *> const_ptrs = {};
17416
17417 bool is_comptime = ir_should_inline(ira->zir, scope)
17418 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
17419
17420
17421 // Here we iterate over the fields that have been initialized, and emit
17422 // compile errors for missing fields and duplicate fields.
17423 // It is only now that we find out whether the struct initialization can be a comptime
17424 // value, but we have already emitted runtime instructions for the fields that
17425 // were initialized with runtime values, and have omitted instructions that would have
17426 // initialized fields with comptime values.
17427 // So now we must clean up this situation. If it turns out the struct initialization can
17428 // be a comptime value, overwrite ConstPtrMutInfer with ConstPtrMutComptimeConst.
17429 // Otherwise, we must emit instructions to runtime-initialize the fields that have
17430 // comptime-known values.
17431
17432 for (size_t i = 0; i < instr_field_count; i += 1) {
17433 Stage1ZirInstContainerInitFieldsField *field = &fields[i];
17434
17435 Stage1AirInst *field_result_loc = field->result_loc->child;
17436 if (type_is_invalid(field_result_loc->value->type))
17437 return ira->codegen->invalid_inst_gen;
17438
17439 TypeStructField *type_field = find_struct_type_field(container_type, field->name);
17440 if (!type_field) {
17441 ir_add_error_node(ira, field->source_node,
17442 buf_sprintf("no field named '%s' in struct '%s'",
17443 buf_ptr(field->name), buf_ptr(&container_type->name)));
17444 return ira->codegen->invalid_inst_gen;
17445 }
17446
17447 if (type_is_invalid(type_field->type_entry))
17448 return ira->codegen->invalid_inst_gen;
17449
17450 size_t field_index = type_field->src_index;
17451 AstNode *existing_assign_node = field_assign_nodes[field_index];
17452 if (existing_assign_node) {
17453 ErrorMsg *msg = ir_add_error_node(ira, field->source_node, buf_sprintf("duplicate field"));
17454 add_error_note(ira->codegen, msg, existing_assign_node, buf_sprintf("other field here"));
17455 return ira->codegen->invalid_inst_gen;
17456 }
17457 field_assign_nodes[field_index] = field->source_node;
17458
17459 if (instr_is_comptime(field_result_loc) &&
17460 field_result_loc->value->data.x_ptr.mut != ConstPtrMutRuntimeVar)
17461 {
17462 const_ptrs.append(field_result_loc);
17463 } else {
17464 first_non_const_instruction = field_result_loc;
17465 }
17466 }
17467
17468 bool any_missing = false;
17469 for (size_t i = 0; i < actual_field_count; i += 1) {
17470 if (field_assign_nodes[i] != nullptr) continue;
17471
17472 // look for a default field value
17473 TypeStructField *field = container_type->data.structure.fields[i];
17474 memoize_field_init_val(ira->codegen, container_type, field);
17475 if (field->init_val == nullptr) {
17476 ir_add_error_node(ira, source_node,
17477 buf_sprintf("missing field: '%s'", buf_ptr(field->name)));
17478 any_missing = true;
17479 continue;
17480 }
17481 if (type_is_invalid(field->init_val->type))
17482 return ira->codegen->invalid_inst_gen;
17483
17484 Stage1AirInst *runtime_inst = ir_const(ira, scope, source_node, field->init_val->type);
17485 copy_const_val(ira->codegen, runtime_inst->value, field->init_val);
17486
17487 Stage1AirInst *field_ptr = ir_analyze_struct_field_ptr(ira, scope, source_node, field, result_loc,
17488 container_type, true);
17489 ir_analyze_store_ptr(ira, scope, source_node, field_ptr, runtime_inst, false);
17490 if (instr_is_comptime(field_ptr) && field_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
17491 const_ptrs.append(field_ptr);
17492 } else {
17493 first_non_const_instruction = result_loc;
17494 }
17495 }
17496 heap::c_allocator.deallocate(field_assign_nodes, actual_field_count);
17497 if (any_missing)
17498 return ira->codegen->invalid_inst_gen;
17499
17500 if (result_loc->value->data.x_ptr.mut == ConstPtrMutInfer) {
17501 if (const_ptrs.length != actual_field_count) {
17502 result_loc->value->special = ConstValSpecialRuntime;
17503 for (size_t i = 0; i < const_ptrs.length; i += 1) {
17504 Stage1AirInst *field_result_loc = const_ptrs.at(i);
17505 Stage1AirInst *deref = ir_get_deref(ira, field_result_loc->scope,
17506 field_result_loc->source_node, field_result_loc, nullptr);
17507 field_result_loc->value->special = ConstValSpecialRuntime;
17508 ir_analyze_store_ptr(ira, field_result_loc->scope, field_result_loc->source_node,
17509 field_result_loc, deref, false);
17510 }
17511 }
17512 }
17513
17514 const_ptrs.deinit();
17515 Stage1AirInst *result = ir_get_deref(ira, scope, source_node, result_loc, nullptr);
17516
17517 if (is_comptime && !instr_is_comptime(result)) {
17518 ir_add_error_node(ira, first_non_const_instruction->source_node,
17519 buf_sprintf("unable to evaluate constant expression"));
17520 return ira->codegen->invalid_inst_gen;
17521 }
17522
17523 return result;
17524}
17525
17526static Stage1AirInst *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
17527 Stage1ZirInstContainerInitList *instruction)
17528{
17529 src_assert(instruction->result_loc != nullptr, instruction->base.source_node);
17530 Stage1AirInst *result_loc = instruction->result_loc->child;
17531 if (type_is_invalid(result_loc->value->type))
17532 return result_loc;
17533
17534 src_assert(result_loc->value->type->id == ZigTypeIdPointer, instruction->base.source_node);
17535 if (result_loc->value->type->data.pointer.is_const) {
17536 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("cannot assign to constant"));
17537 return ira->codegen->invalid_inst_gen;
17538 }
17539
17540 ZigType *container_type = result_loc->value->type->data.pointer.child_type;
17541 size_t elem_count = instruction->item_count;
17542
17543 if (is_slice(container_type)) {
17544 ir_add_error_node(ira, instruction->init_array_type_source_node,
17545 buf_sprintf("array literal requires address-of operator (&) to coerce to slice type '%s'",
17546 buf_ptr(&container_type->name)));
17547 return ira->codegen->invalid_inst_gen;
17548 }
17549
17550 if (container_type->id == ZigTypeIdVoid) {
17551 if (elem_count != 0) {
17552 ir_add_error_node(ira, instruction->base.source_node,
17553 buf_sprintf("void expression expects no arguments"));
17554 return ira->codegen->invalid_inst_gen;
17555 }
17556 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
17557 }
17558
17559 if (container_type->id == ZigTypeIdStruct && elem_count == 0) {
17560 src_assert(instruction->result_loc != nullptr, instruction->base.source_node);
17561 Stage1AirInst *result_loc = instruction->result_loc->child;
17562 if (type_is_invalid(result_loc->value->type))
17563 return result_loc;
17564 return ir_analyze_container_init_fields(ira, instruction->base.scope, instruction->base.source_node, container_type, 0, nullptr, result_loc);
17565 }
17566
17567 if (container_type->id == ZigTypeIdArray) {
17568 ZigType *child_type = container_type->data.array.child_type;
17569 if (container_type->data.array.len != elem_count) {
17570 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count, nullptr);
17571
17572 ir_add_error_node(ira, instruction->base.source_node,
17573 buf_sprintf("expected %s literal, found %s literal",
17574 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
17575 return ira->codegen->invalid_inst_gen;
17576 }
17577 } else if (container_type->id == ZigTypeIdStruct &&
17578 container_type->data.structure.resolve_status == ResolveStatusBeingInferred)
17579 {
17580 // We're now done inferring the type.
17581 container_type->data.structure.resolve_status = ResolveStatusUnstarted;
17582 } else if (container_type->id == ZigTypeIdVector || is_tuple(container_type)) {
17583 // OK
17584 } else {
17585 ir_add_error_node(ira, instruction->base.source_node,
17586 buf_sprintf("type '%s' does not support array initialization",
17587 buf_ptr(&container_type->name)));
17588 return ira->codegen->invalid_inst_gen;
17589 }
17590
17591 switch (type_has_one_possible_value(ira->codegen, container_type)) {
17592 case OnePossibleValueInvalid:
17593 return ira->codegen->invalid_inst_gen;
17594 case OnePossibleValueYes:
17595 return ir_const_move(ira, instruction->base.scope, instruction->base.source_node,
17596 get_the_one_possible_value(ira->codegen, container_type));
17597 case OnePossibleValueNo:
17598 break;
17599 }
17600
17601 bool is_comptime;
17602 switch (type_requires_comptime(ira->codegen, container_type)) {
17603 case ReqCompTimeInvalid:
17604 return ira->codegen->invalid_inst_gen;
17605 case ReqCompTimeNo:
17606 is_comptime = ir_should_inline(ira->zir, instruction->base.scope);
17607 break;
17608 case ReqCompTimeYes:
17609 is_comptime = true;
17610 break;
17611 }
17612
17613 Stage1AirInst *first_non_const_instruction = nullptr;
17614
17615 // The Result Location Mechanism has already emitted runtime instructions to
17616 // initialize runtime elements and has omitted instructions for the comptime
17617 // elements. However it is only now that we find out whether the array initialization
17618 // can be a comptime value. So we must clean up the situation. If it turns out
17619 // array initialization can be a comptime value, overwrite ConstPtrMutInfer with
17620 // ConstPtrMutComptimeConst. Otherwise, emit instructions to runtime-initialize the
17621 // elements that have comptime-known values.
17622 ZigList<Stage1AirInst *> const_ptrs = {};
17623
17624 for (size_t i = 0; i < elem_count; i += 1) {
17625 Stage1AirInst *elem_result_loc = instruction->elem_result_loc_list[i]->child;
17626 if (type_is_invalid(elem_result_loc->value->type))
17627 return ira->codegen->invalid_inst_gen;
17628
17629 assert(elem_result_loc->value->type->id == ZigTypeIdPointer);
17630
17631 if (instr_is_comptime(elem_result_loc) &&
17632 elem_result_loc->value->data.x_ptr.mut != ConstPtrMutRuntimeVar)
17633 {
17634 const_ptrs.append(elem_result_loc);
17635 } else {
17636 first_non_const_instruction = elem_result_loc;
17637 }
17638 }
17639
17640 if (result_loc->value->data.x_ptr.mut == ConstPtrMutInfer) {
17641 if (const_ptrs.length != elem_count) {
17642 result_loc->value->special = ConstValSpecialRuntime;
17643 for (size_t i = 0; i < const_ptrs.length; i += 1) {
17644 Stage1AirInst *elem_result_loc = const_ptrs.at(i);
17645 assert(elem_result_loc->value->special == ConstValSpecialStatic);
17646 if (elem_result_loc->value->type->data.pointer.inferred_struct_field != nullptr) {
17647 // This field will be generated comptime; no need to do this.
17648 continue;
17649 }
17650 Stage1AirInst *deref = ir_get_deref(ira, elem_result_loc->scope,
17651 elem_result_loc->source_node, elem_result_loc, nullptr);
17652 elem_result_loc->value->special = ConstValSpecialRuntime;
17653 ir_analyze_store_ptr(ira, elem_result_loc->scope, elem_result_loc->source_node,
17654 elem_result_loc, deref, false);
17655 }
17656 }
17657 }
17658
17659 const_ptrs.deinit();
17660
17661 Stage1AirInst *result = ir_get_deref(ira, instruction->base.scope, instruction->base.source_node,
17662 result_loc, nullptr);
17663 // If the result is a tuple, we are allowed to return a struct that uses ConstValSpecialRuntime fields at comptime.
17664 if (instr_is_comptime(result) || is_tuple(container_type))
17665 return result;
17666
17667 if (is_comptime) {
17668 ir_add_error(ira, first_non_const_instruction,
17669 buf_sprintf("unable to evaluate constant expression"));
17670 return ira->codegen->invalid_inst_gen;
17671 }
17672
17673 ZigType *result_elem_type = result_loc->value->type->data.pointer.child_type;
17674 if (is_slice(result_elem_type)) {
17675 ErrorMsg *msg = ir_add_error_node(ira, instruction->base.source_node,
17676 buf_sprintf("runtime-initialized array cannot be casted to slice type '%s'",
17677 buf_ptr(&result_elem_type->name)));
17678 add_error_note(ira->codegen, msg, first_non_const_instruction->source_node,
17679 buf_sprintf("this value is not comptime-known"));
17680 return ira->codegen->invalid_inst_gen;
17681 }
17682 return result;
17683}
17684
17685static Stage1AirInst *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,
17686 Stage1ZirInstContainerInitFields *instruction)
17687{
17688 src_assert(instruction->result_loc != nullptr, instruction->base.source_node);
17689 Stage1AirInst *result_loc = instruction->result_loc->child;
17690 if (type_is_invalid(result_loc->value->type))
17691 return result_loc;
17692
17693 src_assert(result_loc->value->type->id == ZigTypeIdPointer, instruction->base.source_node);
17694 if (result_loc->value->type->data.pointer.is_const) {
17695 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("cannot assign to constant"));
17696 return ira->codegen->invalid_inst_gen;
17697 }
17698
17699 ZigType *container_type = result_loc->value->type->data.pointer.child_type;
17700
17701 return ir_analyze_container_init_fields(ira, instruction->base.scope, instruction->base.source_node, container_type,
17702 instruction->field_count, instruction->fields, result_loc);
17703}
17704
17705static Stage1AirInst *ir_analyze_instruction_compile_err(IrAnalyze *ira, Stage1ZirInstCompileErr *instruction) {
17706 Stage1AirInst *msg_value = instruction->msg->child;
17707 Buf *msg_buf = ir_resolve_str(ira, msg_value);
17708 if (!msg_buf)
17709 return ira->codegen->invalid_inst_gen;
17710
17711 ir_add_error_node(ira, instruction->base.source_node, msg_buf);
17712
17713 return ira->codegen->invalid_inst_gen;
17714}
17715
17716static Stage1AirInst *ir_analyze_instruction_compile_log(IrAnalyze *ira, Stage1ZirInstCompileLog *instruction) {
17717 Buf buf = BUF_INIT;
17718 fprintf(stderr, "| ");
17719 for (size_t i = 0; i < instruction->msg_count; i += 1) {
17720 Stage1AirInst *msg = instruction->msg_list[i]->child;
17721 if (type_is_invalid(msg->value->type))
17722 return ira->codegen->invalid_inst_gen;
17723 buf_resize(&buf, 0);
17724 if (msg->value->special == ConstValSpecialLazy) {
17725 // Resolve any lazy value that's passed, we need its value
17726 if (ir_resolve_lazy(ira->codegen, msg->source_node, msg->value))
17727 return ira->codegen->invalid_inst_gen;
17728 }
17729 render_const_value(ira->codegen, &buf, msg->value);
17730 const char *comma_str = (i != 0) ? ", " : "";
17731 fprintf(stderr, "%s%s", comma_str, buf_ptr(&buf));
17732 }
17733 fprintf(stderr, "\n");
17734
17735 auto *expr = &instruction->base.source_node->data.fn_call_expr;
17736 if (!expr->seen) {
17737 // Here we bypass higher level functions such as ir_add_error because we do not want
17738 // invalidate_exec to be called.
17739 add_node_error(ira->codegen, instruction->base.source_node, buf_sprintf("found compile log statement"));
17740 }
17741 expr->seen = true;
17742
17743 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
17744}
17745
17746static Stage1AirInst *ir_analyze_instruction_err_name(IrAnalyze *ira, Stage1ZirInstErrName *instruction) {
17747 Stage1AirInst *value = instruction->value->child;
17748 if (type_is_invalid(value->value->type))
17749 return ira->codegen->invalid_inst_gen;
17750
17751 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_global_error_set);
17752 if (type_is_invalid(casted_value->value->type))
17753 return ira->codegen->invalid_inst_gen;
17754
17755 if (instr_is_comptime(casted_value)) {
17756 ZigValue *val = ir_resolve_const(ira, casted_value, UndefBad);
17757 if (val == nullptr)
17758 return ira->codegen->invalid_inst_gen;
17759 ErrorTableEntry *err = casted_value->value->data.x_err_set;
17760 if (!err->cached_error_name_val) {
17761 err->cached_error_name_val = create_sentineled_str_lit(
17762 ira->codegen, &err->name,
17763 ira->codegen->intern.for_zero_byte());
17764 }
17765 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, nullptr);
17766 result->value = err->cached_error_name_val;
17767 return result;
17768 }
17769
17770 ira->codegen->generate_error_name_table = true;
17771
17772 ZigType *u8_ptr_type = get_pointer_to_type_extra2(ira->codegen, ira->codegen->builtin_types.entry_u8,
17773 true, false, PtrLenUnknown, 0, 0, 0, false,
17774 VECTOR_INDEX_NONE, nullptr, ira->codegen->intern.for_zero_byte());
17775 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);
17776 return ir_build_err_name_gen(ira, instruction->base.scope, instruction->base.source_node, value, str_type);
17777}
17778
17779static Stage1AirInst *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, Stage1ZirInstTagName *instruction) {
17780 Error err;
17781 Stage1AirInst *target = instruction->target->child;
17782 if (type_is_invalid(target->value->type))
17783 return ira->codegen->invalid_inst_gen;
17784
17785 ZigType *target_type = target->value->type;
17786
17787 if (target_type->id == ZigTypeIdEnumLiteral) {
17788 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, nullptr);
17789 Buf *field_name = target->value->data.x_enum_literal;
17790 result->value = create_sentineled_str_lit(
17791 ira->codegen, field_name,
17792 ira->codegen->intern.for_zero_byte());
17793 return result;
17794 }
17795
17796 if (target_type->id == ZigTypeIdUnion) {
17797 target = ir_analyze_union_tag(ira, instruction->base.scope, instruction->base.source_node, target);
17798 if (type_is_invalid(target->value->type))
17799 return ira->codegen->invalid_inst_gen;
17800 target_type = target->value->type;
17801 }
17802
17803 if (target_type->id != ZigTypeIdEnum) {
17804 ir_add_error(ira, target,
17805 buf_sprintf("expected enum tag, found '%s'", buf_ptr(&target_type->name)));
17806 return ira->codegen->invalid_inst_gen;
17807 }
17808
17809 if (can_fold_enum_type(target_type)) {
17810 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
17811 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, nullptr);
17812 result->value = create_sentineled_str_lit(
17813 ira->codegen, only_field->name,
17814 ira->codegen->intern.for_zero_byte());
17815 return result;
17816 }
17817
17818 if (instr_is_comptime(target)) {
17819 if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
17820 return ira->codegen->invalid_inst_gen;
17821 TypeEnumField *field = find_enum_field_by_tag(target_type, &target->value->data.x_bigint);
17822 if (field == nullptr) {
17823 Buf *int_buf = buf_alloc();
17824 bigint_append_buf(int_buf, &target->value->data.x_bigint, 10);
17825
17826 ir_add_error(ira, target,
17827 buf_sprintf("no tag by value %s", buf_ptr(int_buf)));
17828 return ira->codegen->invalid_inst_gen;
17829 }
17830 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, nullptr);
17831 result->value = create_sentineled_str_lit(
17832 ira->codegen, field->name,
17833 ira->codegen->intern.for_zero_byte());
17834 return result;
17835 }
17836
17837 ZigType *u8_ptr_type = get_pointer_to_type_extra2(
17838 ira->codegen, ira->codegen->builtin_types.entry_u8,
17839 true, false, PtrLenUnknown, 0, 0, 0, false,
17840 VECTOR_INDEX_NONE, nullptr, ira->codegen->intern.for_zero_byte());
17841 ZigType *result_type = get_slice_type(ira->codegen, u8_ptr_type);
17842 return ir_build_tag_name_gen(ira, instruction->base.scope, instruction->base.source_node, target, result_type);
17843}
17844
17845static Stage1AirInst *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
17846 Stage1ZirInstFieldParentPtr *instruction)
17847{
17848 Error err;
17849 Stage1AirInst *type_value = instruction->type_value->child;
17850 ZigType *container_type = ir_resolve_type(ira, type_value);
17851 if (type_is_invalid(container_type))
17852 return ira->codegen->invalid_inst_gen;
17853
17854 Stage1AirInst *field_name_value = instruction->field_name->child;
17855 Buf *field_name = ir_resolve_str(ira, field_name_value);
17856 if (!field_name)
17857 return ira->codegen->invalid_inst_gen;
17858
17859 Stage1AirInst *field_ptr = instruction->field_ptr->child;
17860 if (type_is_invalid(field_ptr->value->type))
17861 return ira->codegen->invalid_inst_gen;
17862
17863 if (container_type->id != ZigTypeIdStruct) {
17864 ir_add_error(ira, type_value,
17865 buf_sprintf("expected struct type, found '%s'", buf_ptr(&container_type->name)));
17866 return ira->codegen->invalid_inst_gen;
17867 }
17868
17869 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
17870 return ira->codegen->invalid_inst_gen;
17871
17872 TypeStructField *field = find_struct_type_field(container_type, field_name);
17873 if (field == nullptr) {
17874 ir_add_error(ira, field_name_value,
17875 buf_sprintf("struct '%s' has no field '%s'",
17876 buf_ptr(&container_type->name), buf_ptr(field_name)));
17877 return ira->codegen->invalid_inst_gen;
17878 }
17879
17880 if (field_ptr->value->type->id != ZigTypeIdPointer) {
17881 ir_add_error(ira, field_ptr,
17882 buf_sprintf("expected pointer, found '%s'", buf_ptr(&field_ptr->value->type->name)));
17883 return ira->codegen->invalid_inst_gen;
17884 }
17885
17886 bool is_packed = (container_type->data.structure.layout == ContainerLayoutPacked);
17887 uint32_t field_ptr_align = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
17888 uint32_t parent_ptr_align = is_packed ? 1 : get_abi_alignment(ira->codegen, container_type);
17889
17890 ZigType *field_ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
17891 field_ptr->value->type->data.pointer.is_const,
17892 field_ptr->value->type->data.pointer.is_volatile,
17893 PtrLenSingle,
17894 field_ptr_align, 0, 0, false);
17895 Stage1AirInst *casted_field_ptr = ir_implicit_cast(ira, field_ptr, field_ptr_type);
17896 if (type_is_invalid(casted_field_ptr->value->type))
17897 return ira->codegen->invalid_inst_gen;
17898
17899 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, container_type,
17900 casted_field_ptr->value->type->data.pointer.is_const,
17901 casted_field_ptr->value->type->data.pointer.is_volatile,
17902 PtrLenSingle,
17903 parent_ptr_align, 0, 0, false);
17904
17905 if (instr_is_comptime(casted_field_ptr)) {
17906 ZigValue *field_ptr_val = ir_resolve_const(ira, casted_field_ptr, UndefBad);
17907 if (!field_ptr_val)
17908 return ira->codegen->invalid_inst_gen;
17909
17910 if (field_ptr_val->data.x_ptr.special != ConstPtrSpecialBaseStruct) {
17911 ir_add_error(ira, field_ptr, buf_sprintf("pointer value not based on parent struct"));
17912 return ira->codegen->invalid_inst_gen;
17913 }
17914
17915 size_t ptr_field_index = field_ptr_val->data.x_ptr.data.base_struct.field_index;
17916 if (ptr_field_index != field->src_index) {
17917 ir_add_error_node(ira, instruction->base.source_node,
17918 buf_sprintf("field '%s' has index %" ZIG_PRI_usize " but pointer value is index %" ZIG_PRI_usize " of struct '%s'",
17919 buf_ptr(field->name), field->src_index,
17920 ptr_field_index, buf_ptr(&container_type->name)));
17921 return ira->codegen->invalid_inst_gen;
17922 }
17923
17924 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, result_type);
17925 ZigValue *out_val = result->value;
17926 out_val->data.x_ptr.special = ConstPtrSpecialRef;
17927 out_val->data.x_ptr.data.ref.pointee = field_ptr_val->data.x_ptr.data.base_struct.struct_val;
17928 out_val->data.x_ptr.mut = field_ptr_val->data.x_ptr.mut;
17929 return result;
17930 }
17931
17932 return ir_build_field_parent_ptr_gen(ira, instruction->base.scope, instruction->base.source_node, casted_field_ptr, field, result_type);
17933}
17934
17935static TypeStructField *validate_host_int_byte_offset(IrAnalyze *ira,
17936 Stage1AirInst *type_value,
17937 Stage1AirInst *field_name_value,
17938 size_t *byte_offset)
17939{
17940 ZigType *container_type = ir_resolve_type(ira, type_value);
17941 if (type_is_invalid(container_type))
17942 return nullptr;
17943
17944 Error err;
17945 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
17946 return nullptr;
17947
17948 Buf *field_name = ir_resolve_str(ira, field_name_value);
17949 if (!field_name)
17950 return nullptr;
17951
17952 if (container_type->id != ZigTypeIdStruct) {
17953 ir_add_error(ira, type_value,
17954 buf_sprintf("expected struct type, found '%s'", buf_ptr(&container_type->name)));
17955 return nullptr;
17956 }
17957
17958 TypeStructField *field = find_struct_type_field(container_type, field_name);
17959 if (field == nullptr) {
17960 ir_add_error(ira, field_name_value,
17961 buf_sprintf("struct '%s' has no field '%s'",
17962 buf_ptr(&container_type->name), buf_ptr(field_name)));
17963 return nullptr;
17964 }
17965
17966 if (!type_has_bits(ira->codegen, field->type_entry)) {
17967 ir_add_error(ira, field_name_value,
17968 buf_sprintf("zero-bit field '%s' in struct '%s' has no offset",
17969 buf_ptr(field_name), buf_ptr(&container_type->name)));
17970 return nullptr;
17971 }
17972
17973 *byte_offset = field->offset;
17974 return field;
17975}
17976
17977static Stage1AirInst *ir_analyze_instruction_offset_of(IrAnalyze *ira, Stage1ZirInstOffsetOf *instruction) {
17978 Stage1AirInst *type_value = instruction->type_value->child;
17979 if (type_is_invalid(type_value->value->type))
17980 return ira->codegen->invalid_inst_gen;
17981
17982 Stage1AirInst *field_name_value = instruction->field_name->child;
17983 size_t host_int_byte_offset = 0;
17984 TypeStructField *field = nullptr;
17985 if (!(field = validate_host_int_byte_offset(ira, type_value, field_name_value, &host_int_byte_offset)))
17986 return ira->codegen->invalid_inst_gen;
17987
17988 size_t byte_offset = host_int_byte_offset + (field->bit_offset_in_host / 8);
17989 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, byte_offset);
17990}
17991
17992static Stage1AirInst *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira, Stage1ZirInstBitOffsetOf *instruction) {
17993 Stage1AirInst *type_value = instruction->type_value->child;
17994 if (type_is_invalid(type_value->value->type))
17995 return ira->codegen->invalid_inst_gen;
17996 Stage1AirInst *field_name_value = instruction->field_name->child;
17997 size_t host_int_byte_offset = 0;
17998 TypeStructField *field = nullptr;
17999 if (!(field = validate_host_int_byte_offset(ira, type_value, field_name_value, &host_int_byte_offset)))
18000 return ira->codegen->invalid_inst_gen;
18001
18002 size_t bit_offset = host_int_byte_offset * 8 + field->bit_offset_in_host;
18003 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, bit_offset);
18004}
18005
18006static void ensure_field_index(ZigType *type, const char *field_name, size_t index) {
18007 Buf *field_name_buf;
18008
18009 assert(type != nullptr && !type_is_invalid(type));
18010 field_name_buf = buf_create_from_str(field_name);
18011 TypeStructField *field = find_struct_type_field(type, field_name_buf);
18012 buf_deinit(field_name_buf);
18013
18014 if (field == nullptr || field->src_index != index)
18015 zig_panic("reference to unknown field %s", field_name);
18016}
18017
18018static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) {
18019 Error err;
18020 ZigType *type_info_type = get_builtin_type(ira->codegen, "Type");
18021 assert(type_info_type->id == ZigTypeIdUnion);
18022 if ((err = type_resolve(ira->codegen, type_info_type, ResolveStatusSizeKnown))) {
18023 zig_unreachable();
18024 }
18025
18026 if (type_name == nullptr && root == nullptr)
18027 return type_info_type;
18028 else if (type_name == nullptr)
18029 return root;
18030
18031 ZigType *root_type = (root == nullptr) ? type_info_type : root;
18032
18033 ScopeDecls *type_info_scope = get_container_scope(root_type);
18034 assert(type_info_scope != nullptr);
18035
18036 Buf field_name = BUF_INIT;
18037 buf_init_from_str(&field_name, type_name);
18038 auto entry = type_info_scope->decl_table.get(&field_name);
18039 buf_deinit(&field_name);
18040
18041 TldVar *tld = (TldVar *)entry;
18042 assert(tld->base.id == TldIdVar);
18043
18044 ZigVar *var = tld->var;
18045
18046 assert(var->const_value->type->id == ZigTypeIdMetaType);
18047
18048 return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, nullptr, var->const_value);
18049}
18050
18051static Error ir_make_type_info_decls(IrAnalyze *ira, AstNode *source_node, ZigValue *out_val,
18052 ScopeDecls *decls_scope, bool resolve_types)
18053{
18054 Error err;
18055 ZigType *type_info_declaration_type = ir_type_info_get_type(ira, "Declaration", nullptr);
18056 if ((err = type_resolve(ira->codegen, type_info_declaration_type, ResolveStatusSizeKnown)))
18057 return err;
18058
18059 ensure_field_index(type_info_declaration_type, "name", 0);
18060 ensure_field_index(type_info_declaration_type, "is_pub", 1);
18061
18062 if (!resolve_types) {
18063 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, type_info_declaration_type,
18064 false, false, PtrLenUnknown, 0, 0, 0, false);
18065
18066 out_val->special = ConstValSpecialLazy;
18067 out_val->type = get_slice_type(ira->codegen, ptr_type);
18068
18069 LazyValueTypeInfoDecls *lazy_type_info_decls = heap::c_allocator.create<LazyValueTypeInfoDecls>();
18070 lazy_type_info_decls->ira = ira; ira_ref(ira);
18071 out_val->data.x_lazy = &lazy_type_info_decls->base;
18072 lazy_type_info_decls->base.id = LazyValueIdTypeInfoDecls;
18073
18074 lazy_type_info_decls->source_node = source_node;
18075 lazy_type_info_decls->decls_scope = decls_scope;
18076
18077 return ErrorNone;
18078 }
18079
18080 resolve_container_usingnamespace_decls(ira->codegen, decls_scope);
18081
18082 // Loop through our declarations once to figure out how many declarations
18083 // we will generate info for.
18084 int declaration_count = 0;
18085 auto decl_it = decls_scope->decl_table.entry_iterator();
18086 decltype(decls_scope->decl_table)::Entry *curr_entry = nullptr;
18087 while ((curr_entry = decl_it.next()) != nullptr) {
18088 // Skip comptime blocks and test functions.
18089 if (curr_entry->value->id == TldIdCompTime)
18090 continue;
18091
18092 if (curr_entry->value->id == TldIdFn &&
18093 curr_entry->value->source_node->type == NodeTypeTestDecl)
18094 {
18095 continue;
18096 }
18097
18098 if (curr_entry->value->resolution == TldResolutionInvalid)
18099 return ErrorSemanticAnalyzeFail;
18100
18101 declaration_count += 1;
18102 }
18103
18104 ZigValue *declaration_array = ira->codegen->pass1_arena->create<ZigValue>();
18105 declaration_array->special = ConstValSpecialStatic;
18106 declaration_array->type = get_array_type(ira->codegen, type_info_declaration_type, declaration_count, nullptr);
18107 declaration_array->data.x_array.special = ConstArraySpecialNone;
18108 declaration_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(declaration_count);
18109 init_const_slice(ira->codegen, out_val, declaration_array, 0, declaration_count, false, nullptr);
18110
18111 // Loop through the declarations and generate info.
18112 decl_it = decls_scope->decl_table.entry_iterator();
18113 curr_entry = nullptr;
18114 int declaration_index = 0;
18115 while ((curr_entry = decl_it.next()) != nullptr) {
18116 // Skip comptime blocks and test functions.
18117 if (curr_entry->value->id == TldIdCompTime) {
18118 continue;
18119 }
18120 if (curr_entry->value->id == TldIdFn &&
18121 curr_entry->value->source_node->type == NodeTypeTestDecl)
18122 {
18123 continue;
18124 }
18125
18126 ZigValue *declaration_val = &declaration_array->data.x_array.data.s_none.elements[declaration_index];
18127
18128 declaration_val->special = ConstValSpecialStatic;
18129 declaration_val->type = type_info_declaration_type;
18130
18131 ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 2);
18132 ZigValue *name = create_const_str_lit(ira->codegen, curr_entry->key)->data.x_ptr.data.ref.pointee;
18133 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(curr_entry->key), true, nullptr);
18134 inner_fields[1]->special = ConstValSpecialStatic;
18135 inner_fields[1]->type = ira->codegen->builtin_types.entry_bool;
18136 inner_fields[1]->data.x_bool = curr_entry->value->visib_mod == VisibModPub;
18137
18138 declaration_val->data.x_struct.fields = inner_fields;
18139 declaration_index += 1;
18140 }
18141
18142 assert(declaration_index == declaration_count);
18143 return ErrorNone;
18144}
18145
18146static BuiltinPtrSize ptr_len_to_size_enum_index(PtrLen ptr_len) {
18147 switch (ptr_len) {
18148 case PtrLenSingle:
18149 return BuiltinPtrSizeOne;
18150 case PtrLenUnknown:
18151 return BuiltinPtrSizeMany;
18152 case PtrLenC:
18153 return BuiltinPtrSizeC;
18154 }
18155 zig_unreachable();
18156}
18157
18158static PtrLen size_enum_index_to_ptr_len(BuiltinPtrSize size_enum_index) {
18159 switch (size_enum_index) {
18160 case BuiltinPtrSizeOne:
18161 return PtrLenSingle;
18162 case BuiltinPtrSizeMany:
18163 case BuiltinPtrSizeSlice:
18164 return PtrLenUnknown;
18165 case BuiltinPtrSizeC:
18166 return PtrLenC;
18167 }
18168 zig_unreachable();
18169}
18170
18171static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *ptr_type_entry) {
18172 CodeGen *g = ira->codegen;
18173 ZigType *attrs_type;
18174 BuiltinPtrSize size_enum_index;
18175 if (is_slice(ptr_type_entry)) {
18176 TypeStructField *ptr_field = ptr_type_entry->data.structure.fields[slice_ptr_index];
18177 attrs_type = resolve_struct_field_type(g, ptr_field);
18178 size_enum_index = BuiltinPtrSizeSlice;
18179 } else if (ptr_type_entry->id == ZigTypeIdPointer) {
18180 attrs_type = ptr_type_entry;
18181 size_enum_index = ptr_len_to_size_enum_index(ptr_type_entry->data.pointer.ptr_len);
18182 } else {
18183 zig_unreachable();
18184 }
18185
18186 ZigType *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer", nullptr);
18187 assertNoError(type_resolve(g, type_info_pointer_type, ResolveStatusSizeKnown));
18188
18189 ZigValue *result = g->pass1_arena->create<ZigValue>();
18190 result->special = ConstValSpecialStatic;
18191 result->type = type_info_pointer_type;
18192
18193 ZigValue **fields = alloc_const_vals_ptrs(g, 8);
18194 result->data.x_struct.fields = fields;
18195
18196 // size: Size
18197 ensure_field_index(result->type, "size", 0);
18198 ZigType *type_info_pointer_size_type = ir_type_info_get_type(ira, "Size", type_info_pointer_type);
18199 assertNoError(type_resolve(g, type_info_pointer_size_type, ResolveStatusSizeKnown));
18200 fields[0]->special = ConstValSpecialStatic;
18201 fields[0]->type = type_info_pointer_size_type;
18202 bigint_init_unsigned(&fields[0]->data.x_enum_tag, size_enum_index);
18203
18204 // is_const: bool
18205 ensure_field_index(result->type, "is_const", 1);
18206 fields[1]->special = ConstValSpecialStatic;
18207 fields[1]->type = g->builtin_types.entry_bool;
18208 fields[1]->data.x_bool = attrs_type->data.pointer.is_const;
18209 // is_volatile: bool
18210 ensure_field_index(result->type, "is_volatile", 2);
18211 fields[2]->special = ConstValSpecialStatic;
18212 fields[2]->type = g->builtin_types.entry_bool;
18213 fields[2]->data.x_bool = attrs_type->data.pointer.is_volatile;
18214 // alignment: comptime_int
18215 ensure_field_index(result->type, "alignment", 3);
18216 fields[3]->type = g->builtin_types.entry_num_lit_int;
18217 if (attrs_type->data.pointer.explicit_alignment != 0) {
18218 fields[3]->special = ConstValSpecialStatic;
18219 bigint_init_unsigned(&fields[3]->data.x_bigint, attrs_type->data.pointer.explicit_alignment);
18220 } else {
18221 LazyValueAlignOf *lazy_align_of = heap::c_allocator.create<LazyValueAlignOf>();
18222 lazy_align_of->ira = ira; ira_ref(ira);
18223 fields[3]->special = ConstValSpecialLazy;
18224 fields[3]->data.x_lazy = &lazy_align_of->base;
18225 lazy_align_of->base.id = LazyValueIdAlignOf;
18226 lazy_align_of->target_type = ir_const_type(ira, scope, source_node, attrs_type->data.pointer.child_type);
18227 }
18228 // address_space: AddressSpace,
18229 ensure_field_index(result->type, "address_space", 4);
18230 fields[4]->special = ConstValSpecialStatic;
18231 fields[4]->type = get_builtin_type(g, "AddressSpace");
18232 bigint_init_unsigned(&fields[4]->data.x_enum_tag, AddressSpaceGeneric);
18233 // child: type
18234 ensure_field_index(result->type, "child", 5);
18235 fields[5]->special = ConstValSpecialStatic;
18236 fields[5]->type = g->builtin_types.entry_type;
18237 fields[5]->data.x_type = attrs_type->data.pointer.child_type;
18238 // is_allowzero: bool
18239 ensure_field_index(result->type, "is_allowzero", 6);
18240 fields[6]->special = ConstValSpecialStatic;
18241 fields[6]->type = g->builtin_types.entry_bool;
18242 fields[6]->data.x_bool = attrs_type->data.pointer.allow_zero;
18243 // sentinel: ?*const anyopaque
18244 ensure_field_index(result->type, "sentinel", 7);
18245 fields[7]->special = ConstValSpecialStatic;
18246 fields[7]->type = g->builtin_types.entry_opt_ptr_const_anyopaque;
18247 ZigValue *ptr_to_sent = (attrs_type->data.pointer.sentinel == nullptr) ? nullptr :
18248 create_const_ptr_ref(g, attrs_type->data.pointer.sentinel, true);
18249 set_optional_payload(fields[7], ptr_to_sent);
18250
18251 return result;
18252};
18253
18254static void make_enum_field_val(IrAnalyze *ira, ZigValue *enum_field_val, TypeEnumField *enum_field,
18255 ZigType *type_info_enum_field_type)
18256{
18257 enum_field_val->special = ConstValSpecialStatic;
18258 enum_field_val->type = type_info_enum_field_type;
18259
18260 ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 2);
18261 inner_fields[1]->special = ConstValSpecialStatic;
18262 inner_fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int;
18263
18264 ZigValue *name = create_const_str_lit(ira->codegen, enum_field->name)->data.x_ptr.data.ref.pointee;
18265 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(enum_field->name), true, nullptr);
18266
18267 bigint_init_bigint(&inner_fields[1]->data.x_bigint, &enum_field->value);
18268
18269 enum_field_val->data.x_struct.fields = inner_fields;
18270}
18271
18272static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *type_entry,
18273 ZigValue **out)
18274{
18275 Error err;
18276 assert(type_entry != nullptr);
18277 assert(!type_is_invalid(type_entry));
18278
18279 CodeGen *g = ira->codegen;
18280
18281 auto entry = g->type_info_cache.maybe_get(type_entry);
18282 if (entry != nullptr) {
18283 *out = entry->value;
18284 return ErrorNone;
18285 }
18286
18287 ZigValue *result = nullptr;
18288 switch (type_entry->id) {
18289 case ZigTypeIdInvalid:
18290 zig_unreachable();
18291 case ZigTypeIdMetaType:
18292 case ZigTypeIdVoid:
18293 case ZigTypeIdBool:
18294 case ZigTypeIdUnreachable:
18295 case ZigTypeIdComptimeFloat:
18296 case ZigTypeIdComptimeInt:
18297 case ZigTypeIdEnumLiteral:
18298 case ZigTypeIdUndefined:
18299 case ZigTypeIdNull:
18300 result = g->intern.for_void();
18301 break;
18302 case ZigTypeIdInt:
18303 {
18304 result = g->pass1_arena->create<ZigValue>();
18305 result->special = ConstValSpecialStatic;
18306 result->type = ir_type_info_get_type(ira, "Int", nullptr);
18307
18308 ZigValue **fields = alloc_const_vals_ptrs(g, 2);
18309 result->data.x_struct.fields = fields;
18310
18311 // is_signed: Signedness
18312 ensure_field_index(result->type, "signedness", 0);
18313 fields[0]->special = ConstValSpecialStatic;
18314 fields[0]->type = get_builtin_type(g, "Signedness");
18315 bigint_init_unsigned(&fields[0]->data.x_enum_tag, !type_entry->data.integral.is_signed);
18316 // bits: u8
18317 ensure_field_index(result->type, "bits", 1);
18318 fields[1]->special = ConstValSpecialStatic;
18319 fields[1]->type = g->builtin_types.entry_num_lit_int;
18320 bigint_init_unsigned(&fields[1]->data.x_bigint, type_entry->data.integral.bit_count);
18321
18322 break;
18323 }
18324 case ZigTypeIdFloat:
18325 {
18326 result = g->pass1_arena->create<ZigValue>();
18327 result->special = ConstValSpecialStatic;
18328 result->type = ir_type_info_get_type(ira, "Float", nullptr);
18329
18330 ZigValue **fields = alloc_const_vals_ptrs(g, 1);
18331 result->data.x_struct.fields = fields;
18332
18333 // bits: u8
18334 ensure_field_index(result->type, "bits", 0);
18335 fields[0]->special = ConstValSpecialStatic;
18336 fields[0]->type = g->builtin_types.entry_num_lit_int;
18337 bigint_init_unsigned(&fields[0]->data.x_bigint, type_entry->data.floating.bit_count);
18338
18339 break;
18340 }
18341 case ZigTypeIdPointer:
18342 {
18343 result = create_ptr_like_type_info(ira, scope, source_node, type_entry);
18344 if (result == nullptr)
18345 return ErrorSemanticAnalyzeFail;
18346 break;
18347 }
18348 case ZigTypeIdArray:
18349 {
18350 result = g->pass1_arena->create<ZigValue>();
18351 result->special = ConstValSpecialStatic;
18352 result->type = ir_type_info_get_type(ira, "Array", nullptr);
18353
18354 ZigValue **fields = alloc_const_vals_ptrs(g, 3);
18355 result->data.x_struct.fields = fields;
18356
18357 // len: usize
18358 ensure_field_index(result->type, "len", 0);
18359 fields[0]->special = ConstValSpecialStatic;
18360 fields[0]->type = g->builtin_types.entry_num_lit_int;
18361 bigint_init_unsigned(&fields[0]->data.x_bigint, type_entry->data.array.len);
18362 // child: type
18363 ensure_field_index(result->type, "child", 1);
18364 fields[1]->special = ConstValSpecialStatic;
18365 fields[1]->type = g->builtin_types.entry_type;
18366 fields[1]->data.x_type = type_entry->data.array.child_type;
18367 src_assert(type_entry->data.array.child_type != nullptr, source_node);
18368 // sentinel: ?*const anyopaque
18369 fields[2]->special = ConstValSpecialStatic;
18370 fields[2]->type = g->builtin_types.entry_opt_ptr_const_anyopaque;
18371 ZigValue *ptr_to_sent = (type_entry->data.array.sentinel == nullptr) ? nullptr :
18372 create_const_ptr_ref(g, type_entry->data.array.sentinel, true);
18373 set_optional_payload(fields[2], ptr_to_sent);
18374 break;
18375 }
18376 case ZigTypeIdVector: {
18377 result = g->pass1_arena->create<ZigValue>();
18378 result->special = ConstValSpecialStatic;
18379 result->type = ir_type_info_get_type(ira, "Vector", nullptr);
18380
18381 ZigValue **fields = alloc_const_vals_ptrs(g, 2);
18382 result->data.x_struct.fields = fields;
18383
18384 // len: usize
18385 ensure_field_index(result->type, "len", 0);
18386 fields[0]->special = ConstValSpecialStatic;
18387 fields[0]->type = g->builtin_types.entry_num_lit_int;
18388 bigint_init_unsigned(&fields[0]->data.x_bigint, type_entry->data.vector.len);
18389 // child: type
18390 ensure_field_index(result->type, "child", 1);
18391 fields[1]->special = ConstValSpecialStatic;
18392 fields[1]->type = g->builtin_types.entry_type;
18393 fields[1]->data.x_type = type_entry->data.vector.elem_type;
18394
18395 break;
18396 }
18397 case ZigTypeIdOptional:
18398 {
18399 result = g->pass1_arena->create<ZigValue>();
18400 result->special = ConstValSpecialStatic;
18401 result->type = ir_type_info_get_type(ira, "Optional", nullptr);
18402
18403 ZigValue **fields = alloc_const_vals_ptrs(g, 1);
18404 result->data.x_struct.fields = fields;
18405
18406 // child: type
18407 ensure_field_index(result->type, "child", 0);
18408 fields[0]->special = ConstValSpecialStatic;
18409 fields[0]->type = g->builtin_types.entry_type;
18410 fields[0]->data.x_type = type_entry->data.maybe.child_type;
18411
18412 break;
18413 }
18414 case ZigTypeIdAnyFrame: {
18415 result = g->pass1_arena->create<ZigValue>();
18416 result->special = ConstValSpecialStatic;
18417 result->type = ir_type_info_get_type(ira, "AnyFrame", nullptr);
18418
18419 ZigValue **fields = alloc_const_vals_ptrs(g, 1);
18420 result->data.x_struct.fields = fields;
18421
18422 // child: ?type
18423 ensure_field_index(result->type, "child", 0);
18424 fields[0]->special = ConstValSpecialStatic;
18425 fields[0]->type = get_optional_type(g, g->builtin_types.entry_type);
18426 fields[0]->data.x_optional = (type_entry->data.any_frame.result_type == nullptr) ? nullptr :
18427 create_const_type(g, type_entry->data.any_frame.result_type);
18428 break;
18429 }
18430 case ZigTypeIdEnum:
18431 {
18432 if ((err = type_resolve(g, type_entry, ResolveStatusSizeKnown)))
18433 return err;
18434
18435 result = g->pass1_arena->create<ZigValue>();
18436 result->special = ConstValSpecialStatic;
18437 result->type = ir_type_info_get_type(ira, "Enum", nullptr);
18438
18439 ZigValue **fields = alloc_const_vals_ptrs(g, 5);
18440 result->data.x_struct.fields = fields;
18441
18442 // layout: ContainerLayout
18443 ensure_field_index(result->type, "layout", 0);
18444 fields[0]->special = ConstValSpecialStatic;
18445 fields[0]->type = ir_type_info_get_type(ira, "ContainerLayout", nullptr);
18446 bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.enumeration.layout);
18447 // tag_type: type
18448 ensure_field_index(result->type, "tag_type", 1);
18449 fields[1]->special = ConstValSpecialStatic;
18450 fields[1]->type = g->builtin_types.entry_type;
18451 fields[1]->data.x_type = type_entry->data.enumeration.tag_int_type;
18452 // fields: []Type.EnumField
18453 ensure_field_index(result->type, "fields", 2);
18454
18455 ZigType *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField", nullptr);
18456 if ((err = type_resolve(g, type_info_enum_field_type, ResolveStatusSizeKnown))) {
18457 zig_unreachable();
18458 }
18459 uint32_t enum_field_count = type_entry->data.enumeration.src_field_count;
18460
18461 ZigValue *enum_field_array = g->pass1_arena->create<ZigValue>();
18462 enum_field_array->special = ConstValSpecialStatic;
18463 enum_field_array->type = get_array_type(g, type_info_enum_field_type, enum_field_count, nullptr);
18464 enum_field_array->data.x_array.special = ConstArraySpecialNone;
18465 enum_field_array->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(enum_field_count);
18466
18467 init_const_slice(g, fields[2], enum_field_array, 0, enum_field_count, false, nullptr);
18468
18469 for (uint32_t enum_field_index = 0; enum_field_index < enum_field_count; enum_field_index++)
18470 {
18471 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index];
18472 ZigValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index];
18473 make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type);
18474 enum_field_val->parent.id = ConstParentIdArray;
18475 enum_field_val->parent.data.p_array.array_val = enum_field_array;
18476 enum_field_val->parent.data.p_array.elem_index = enum_field_index;
18477 }
18478 // decls: []Type.Declaration
18479 ensure_field_index(result->type, "decls", 3);
18480 if ((err = ir_make_type_info_decls(ira, source_node, fields[3],
18481 type_entry->data.enumeration.decls_scope, false)))
18482 {
18483 return err;
18484 }
18485 // is_exhaustive: bool
18486 ensure_field_index(result->type, "is_exhaustive", 4);
18487 fields[4]->special = ConstValSpecialStatic;
18488 fields[4]->type = g->builtin_types.entry_bool;
18489 fields[4]->data.x_bool = !type_entry->data.enumeration.non_exhaustive;
18490
18491 break;
18492 }
18493 case ZigTypeIdErrorSet:
18494 {
18495 result = g->pass1_arena->create<ZigValue>();
18496 result->special = ConstValSpecialStatic;
18497 result->type = ir_type_info_get_type(ira, "ErrorSet", nullptr);
18498
18499 ZigType *type_info_error_type = ir_type_info_get_type(ira, "Error", nullptr);
18500 if (!resolve_inferred_error_set(g, type_entry, source_node)) {
18501 return ErrorSemanticAnalyzeFail;
18502 }
18503 if (type_is_global_error_set(type_entry)) {
18504 result->data.x_optional = nullptr;
18505 break;
18506 }
18507 if ((err = type_resolve(g, type_info_error_type, ResolveStatusSizeKnown))) {
18508 zig_unreachable();
18509 }
18510 ZigValue *slice_val = g->pass1_arena->create<ZigValue>();
18511 result->data.x_optional = slice_val;
18512
18513 uint32_t error_count = type_entry->data.error_set.err_count;
18514 ZigValue *error_array = g->pass1_arena->create<ZigValue>();
18515 error_array->special = ConstValSpecialStatic;
18516 error_array->type = get_array_type(g, type_info_error_type, error_count, nullptr);
18517 error_array->data.x_array.special = ConstArraySpecialNone;
18518 error_array->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(error_count);
18519
18520 init_const_slice(g, slice_val, error_array, 0, error_count, false, nullptr);
18521 for (uint32_t error_index = 0; error_index < error_count; error_index++) {
18522 ErrorTableEntry *error = type_entry->data.error_set.errors[error_index];
18523 ZigValue *error_val = &error_array->data.x_array.data.s_none.elements[error_index];
18524
18525 error_val->special = ConstValSpecialStatic;
18526 error_val->type = type_info_error_type;
18527
18528 ZigValue **inner_fields = alloc_const_vals_ptrs(g, 1);
18529
18530 ZigValue *name = nullptr;
18531 if (error->cached_error_name_val != nullptr)
18532 name = error->cached_error_name_val;
18533 if (name == nullptr)
18534 name = create_const_str_lit(g, &error->name)->data.x_ptr.data.ref.pointee;
18535 init_const_slice(g, inner_fields[0], name, 0, buf_len(&error->name), true, nullptr);
18536
18537 error_val->data.x_struct.fields = inner_fields;
18538 error_val->parent.id = ConstParentIdArray;
18539 error_val->parent.data.p_array.array_val = error_array;
18540 error_val->parent.data.p_array.elem_index = error_index;
18541 }
18542
18543 break;
18544 }
18545 case ZigTypeIdErrorUnion:
18546 {
18547 result = g->pass1_arena->create<ZigValue>();
18548 result->special = ConstValSpecialStatic;
18549 result->type = ir_type_info_get_type(ira, "ErrorUnion", nullptr);
18550
18551 ZigValue **fields = alloc_const_vals_ptrs(g, 2);
18552 result->data.x_struct.fields = fields;
18553
18554 // error_set: type
18555 ensure_field_index(result->type, "error_set", 0);
18556 fields[0]->special = ConstValSpecialStatic;
18557 fields[0]->type = g->builtin_types.entry_type;
18558 fields[0]->data.x_type = type_entry->data.error_union.err_set_type;
18559
18560 // payload: type
18561 ensure_field_index(result->type, "payload", 1);
18562 fields[1]->special = ConstValSpecialStatic;
18563 fields[1]->type = g->builtin_types.entry_type;
18564 fields[1]->data.x_type = type_entry->data.error_union.payload_type;
18565
18566 break;
18567 }
18568 case ZigTypeIdUnion:
18569 {
18570 if ((err = type_resolve(g, type_entry, ResolveStatusSizeKnown)))
18571 return err;
18572
18573 result = g->pass1_arena->create<ZigValue>();
18574 result->special = ConstValSpecialStatic;
18575 result->type = ir_type_info_get_type(ira, "Union", nullptr);
18576
18577 ZigValue **fields = alloc_const_vals_ptrs(g, 4);
18578 result->data.x_struct.fields = fields;
18579
18580 // layout: ContainerLayout
18581 ensure_field_index(result->type, "layout", 0);
18582 fields[0]->special = ConstValSpecialStatic;
18583 fields[0]->type = ir_type_info_get_type(ira, "ContainerLayout", nullptr);
18584 bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.unionation.layout);
18585 // tag_type: ?type
18586 ensure_field_index(result->type, "tag_type", 1);
18587 fields[1]->special = ConstValSpecialStatic;
18588 fields[1]->type = get_optional_type(g, g->builtin_types.entry_type);
18589
18590 AstNode *union_decl_node = type_entry->data.unionation.decl_node;
18591 if (union_decl_node->data.container_decl.auto_enum ||
18592 union_decl_node->data.container_decl.init_arg_expr != nullptr)
18593 {
18594 ZigValue *tag_type = g->pass1_arena->create<ZigValue>();
18595 tag_type->special = ConstValSpecialStatic;
18596 tag_type->type = g->builtin_types.entry_type;
18597 tag_type->data.x_type = type_entry->data.unionation.tag_type;
18598 fields[1]->data.x_optional = tag_type;
18599 } else {
18600 fields[1]->data.x_optional = nullptr;
18601 }
18602 // fields: []Type.UnionField
18603 ensure_field_index(result->type, "fields", 2);
18604
18605 ZigType *type_info_union_field_type = ir_type_info_get_type(ira, "UnionField", nullptr);
18606 if ((err = type_resolve(g, type_info_union_field_type, ResolveStatusSizeKnown)))
18607 zig_unreachable();
18608 uint32_t union_field_count = type_entry->data.unionation.src_field_count;
18609
18610 ZigValue *union_field_array = g->pass1_arena->create<ZigValue>();
18611 union_field_array->special = ConstValSpecialStatic;
18612 union_field_array->type = get_array_type(g, type_info_union_field_type, union_field_count, nullptr);
18613 union_field_array->data.x_array.special = ConstArraySpecialNone;
18614 union_field_array->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(union_field_count);
18615
18616 init_const_slice(g, fields[2], union_field_array, 0, union_field_count, false, nullptr);
18617
18618 for (uint32_t union_field_index = 0; union_field_index < union_field_count; union_field_index++) {
18619 TypeUnionField *union_field = &type_entry->data.unionation.fields[union_field_index];
18620 ZigValue *union_field_val = &union_field_array->data.x_array.data.s_none.elements[union_field_index];
18621
18622 union_field_val->special = ConstValSpecialStatic;
18623 union_field_val->type = type_info_union_field_type;
18624
18625 ZigValue **inner_fields = alloc_const_vals_ptrs(g, 3);
18626 // field_type: type
18627 inner_fields[1]->special = ConstValSpecialStatic;
18628 inner_fields[1]->type = g->builtin_types.entry_type;
18629 inner_fields[1]->data.x_type = union_field->type_entry;
18630
18631 // alignment: comptime_int
18632 inner_fields[2]->special = ConstValSpecialStatic;
18633 inner_fields[2]->type = g->builtin_types.entry_num_lit_int;
18634 bigint_init_unsigned(&inner_fields[2]->data.x_bigint, union_field->align);
18635
18636 ZigValue *name = create_const_str_lit(g, union_field->name)->data.x_ptr.data.ref.pointee;
18637 init_const_slice(g, inner_fields[0], name, 0, buf_len(union_field->name), true, nullptr);
18638
18639 union_field_val->data.x_struct.fields = inner_fields;
18640 union_field_val->parent.id = ConstParentIdArray;
18641 union_field_val->parent.data.p_array.array_val = union_field_array;
18642 union_field_val->parent.data.p_array.elem_index = union_field_index;
18643 }
18644 // decls: []Type.Declaration
18645 ensure_field_index(result->type, "decls", 3);
18646 if ((err = ir_make_type_info_decls(ira, source_node, fields[3],
18647 type_entry->data.unionation.decls_scope, false)))
18648 {
18649 return err;
18650 }
18651
18652 break;
18653 }
18654 case ZigTypeIdStruct:
18655 {
18656 if (type_entry->data.structure.special == StructSpecialSlice) {
18657 result = create_ptr_like_type_info(ira, scope, source_node, type_entry);
18658 if (result == nullptr)
18659 return ErrorSemanticAnalyzeFail;
18660 break;
18661 }
18662
18663 if ((err = type_resolve(g, type_entry, ResolveStatusSizeKnown)))
18664 return err;
18665
18666 result = g->pass1_arena->create<ZigValue>();
18667 result->special = ConstValSpecialStatic;
18668 result->type = ir_type_info_get_type(ira, "Struct", nullptr);
18669
18670 ZigValue **fields = alloc_const_vals_ptrs(g, 5);
18671 result->data.x_struct.fields = fields;
18672
18673 // layout: ContainerLayout
18674 ensure_field_index(result->type, "layout", 0);
18675 fields[0]->special = ConstValSpecialStatic;
18676 fields[0]->type = ir_type_info_get_type(ira, "ContainerLayout", nullptr);
18677 bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.structure.layout);
18678
18679 // backing_integer: ?type
18680 ensure_field_index(result->type, "backing_integer", 1);
18681 fields[1]->special = ConstValSpecialStatic;
18682 fields[1]->type = get_optional_type(g, g->builtin_types.entry_type);
18683 // This is always null in stage1, as stage1 does not support explicit backing integers
18684 // for packed structs.
18685 fields[1]->data.x_optional = nullptr;
18686
18687 // fields: []Type.StructField
18688 ensure_field_index(result->type, "fields", 2);
18689
18690 ZigType *type_info_struct_field_type = ir_type_info_get_type(ira, "StructField", nullptr);
18691 if ((err = type_resolve(g, type_info_struct_field_type, ResolveStatusSizeKnown))) {
18692 zig_unreachable();
18693 }
18694 uint32_t struct_field_count = type_entry->data.structure.src_field_count;
18695
18696 ZigValue *struct_field_array = g->pass1_arena->create<ZigValue>();
18697 struct_field_array->special = ConstValSpecialStatic;
18698 struct_field_array->type = get_array_type(g, type_info_struct_field_type, struct_field_count, nullptr);
18699 struct_field_array->data.x_array.special = ConstArraySpecialNone;
18700 struct_field_array->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(struct_field_count);
18701
18702 init_const_slice(g, fields[2], struct_field_array, 0, struct_field_count, false, nullptr);
18703
18704 for (uint32_t struct_field_index = 0; struct_field_index < struct_field_count; struct_field_index++) {
18705 TypeStructField *struct_field = type_entry->data.structure.fields[struct_field_index];
18706 ZigValue *struct_field_val = &struct_field_array->data.x_array.data.s_none.elements[struct_field_index];
18707
18708 struct_field_val->special = ConstValSpecialStatic;
18709 struct_field_val->type = type_info_struct_field_type;
18710
18711 ZigValue **inner_fields = alloc_const_vals_ptrs(g, 5);
18712
18713 inner_fields[1]->special = ConstValSpecialStatic;
18714 inner_fields[1]->type = g->builtin_types.entry_type;
18715 inner_fields[1]->data.x_type = struct_field->type_entry;
18716
18717 // default_value: ?*const anyopaque
18718 inner_fields[2]->special = ConstValSpecialStatic;
18719 inner_fields[2]->type = g->builtin_types.entry_opt_ptr_const_anyopaque;
18720 memoize_field_init_val(g, type_entry, struct_field);
18721 if (struct_field->init_val != nullptr &&
18722 type_is_invalid(struct_field->init_val->type))
18723 {
18724 return ErrorSemanticAnalyzeFail;
18725 }
18726 ZigValue *ptr_to_sent = (struct_field->init_val == nullptr) ? nullptr :
18727 create_const_ptr_ref(g, struct_field->init_val, true);
18728 set_optional_payload(inner_fields[2], ptr_to_sent);
18729
18730 // is_comptime: bool
18731 inner_fields[3]->special = ConstValSpecialStatic;
18732 inner_fields[3]->type = g->builtin_types.entry_bool;
18733 inner_fields[3]->data.x_bool = struct_field->is_comptime;
18734
18735 // alignment: comptime_int
18736 inner_fields[4]->special = ConstValSpecialStatic;
18737 inner_fields[4]->type = g->builtin_types.entry_num_lit_int;
18738 bigint_init_unsigned(&inner_fields[4]->data.x_bigint, struct_field->align);
18739
18740 ZigValue *name = create_const_str_lit(g, struct_field->name)->data.x_ptr.data.ref.pointee;
18741 init_const_slice(g, inner_fields[0], name, 0, buf_len(struct_field->name), true, nullptr);
18742
18743 struct_field_val->data.x_struct.fields = inner_fields;
18744 struct_field_val->parent.id = ConstParentIdArray;
18745 struct_field_val->parent.data.p_array.array_val = struct_field_array;
18746 struct_field_val->parent.data.p_array.elem_index = struct_field_index;
18747 }
18748 // decls: []Type.Declaration
18749 ensure_field_index(result->type, "decls", 3);
18750 if ((err = ir_make_type_info_decls(ira, source_node, fields[3],
18751 type_entry->data.structure.decls_scope, false)))
18752 {
18753 return err;
18754 }
18755
18756 // is_tuple: bool
18757 ensure_field_index(result->type, "is_tuple", 4);
18758 fields[4]->special = ConstValSpecialStatic;
18759 fields[4]->type = g->builtin_types.entry_bool;
18760 fields[4]->data.x_bool = is_tuple(type_entry);
18761
18762 break;
18763 }
18764 case ZigTypeIdFn:
18765 {
18766 result = g->pass1_arena->create<ZigValue>();
18767 result->special = ConstValSpecialStatic;
18768 result->type = ir_type_info_get_type(ira, "Fn", nullptr);
18769
18770 ZigValue **fields = alloc_const_vals_ptrs(g, 7);
18771 result->data.x_struct.fields = fields;
18772
18773 // calling_convention: Type.CallingConvention
18774 ensure_field_index(result->type, "calling_convention", 0);
18775 fields[0]->special = ConstValSpecialStatic;
18776 fields[0]->type = get_builtin_type(g, "CallingConvention");
18777 bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.fn.fn_type_id.cc);
18778 // alignment: comptime_int
18779 ensure_field_index(result->type, "alignment", 1);
18780 fields[1]->special = ConstValSpecialStatic;
18781 fields[1]->type = g->builtin_types.entry_num_lit_int;
18782 bigint_init_unsigned(&fields[1]->data.x_bigint, get_ptr_align(g, type_entry));
18783 // is_generic: bool
18784 ensure_field_index(result->type, "is_generic", 2);
18785 bool is_generic = type_entry->data.fn.is_generic;
18786 fields[2]->special = ConstValSpecialStatic;
18787 fields[2]->type = g->builtin_types.entry_bool;
18788 fields[2]->data.x_bool = is_generic;
18789 // is_varargs: bool
18790 ensure_field_index(result->type, "is_var_args", 3);
18791 bool is_varargs = type_entry->data.fn.fn_type_id.is_var_args;
18792 fields[3]->special = ConstValSpecialStatic;
18793 fields[3]->type = g->builtin_types.entry_bool;
18794 fields[3]->data.x_bool = is_varargs;
18795 // return_type: ?type
18796 ensure_field_index(result->type, "return_type", 4);
18797 fields[4]->special = ConstValSpecialStatic;
18798 fields[4]->type = get_optional_type(g, g->builtin_types.entry_type);
18799 if (type_entry->data.fn.fn_type_id.return_type == nullptr)
18800 fields[4]->data.x_optional = nullptr;
18801 else {
18802 ZigValue *return_type = g->pass1_arena->create<ZigValue>();
18803 return_type->special = ConstValSpecialStatic;
18804 return_type->type = g->builtin_types.entry_type;
18805 return_type->data.x_type = type_entry->data.fn.fn_type_id.return_type;
18806 fields[4]->data.x_optional = return_type;
18807 }
18808 // args: []Type.Fn.Param
18809 ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "Param", result->type);
18810 if ((err = type_resolve(g, type_info_fn_arg_type, ResolveStatusSizeKnown))) {
18811 zig_unreachable();
18812 }
18813 size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count;
18814
18815 ZigValue *fn_arg_array = g->pass1_arena->create<ZigValue>();
18816 fn_arg_array->special = ConstValSpecialStatic;
18817 fn_arg_array->type = get_array_type(g, type_info_fn_arg_type, fn_arg_count, nullptr);
18818 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
18819 fn_arg_array->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(fn_arg_count);
18820
18821 init_const_slice(g, fields[5], fn_arg_array, 0, fn_arg_count, false, nullptr);
18822
18823 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {
18824 FnTypeParamInfo *fn_param_info = &type_entry->data.fn.fn_type_id.param_info[fn_arg_index];
18825 ZigValue *fn_arg_val = &fn_arg_array->data.x_array.data.s_none.elements[fn_arg_index];
18826
18827 fn_arg_val->special = ConstValSpecialStatic;
18828 fn_arg_val->type = type_info_fn_arg_type;
18829
18830 bool arg_is_generic = fn_param_info->type == nullptr;
18831 if (arg_is_generic) assert(is_generic);
18832
18833 ZigValue **inner_fields = alloc_const_vals_ptrs(g, 3);
18834 inner_fields[0]->special = ConstValSpecialStatic;
18835 inner_fields[0]->type = g->builtin_types.entry_bool;
18836 inner_fields[0]->data.x_bool = arg_is_generic;
18837 inner_fields[1]->special = ConstValSpecialStatic;
18838 inner_fields[1]->type = g->builtin_types.entry_bool;
18839 inner_fields[1]->data.x_bool = fn_param_info->is_noalias;
18840 inner_fields[2]->special = ConstValSpecialStatic;
18841 inner_fields[2]->type = get_optional_type(g, g->builtin_types.entry_type);
18842
18843 if (arg_is_generic)
18844 inner_fields[2]->data.x_optional = nullptr;
18845 else {
18846 ZigValue *arg_type = g->pass1_arena->create<ZigValue>();
18847 arg_type->special = ConstValSpecialStatic;
18848 arg_type->type = g->builtin_types.entry_type;
18849 arg_type->data.x_type = fn_param_info->type;
18850 inner_fields[2]->data.x_optional = arg_type;
18851 }
18852
18853 fn_arg_val->data.x_struct.fields = inner_fields;
18854 fn_arg_val->parent.id = ConstParentIdArray;
18855 fn_arg_val->parent.data.p_array.array_val = fn_arg_array;
18856 fn_arg_val->parent.data.p_array.elem_index = fn_arg_index;
18857 }
18858
18859 break;
18860 }
18861 case ZigTypeIdBoundFn:
18862 {
18863 ZigType *fn_type = type_entry->data.bound_fn.fn_type;
18864 assert(fn_type->id == ZigTypeIdFn);
18865 if ((err = ir_make_type_info_value(ira, scope, source_node, fn_type, &result)))
18866 return err;
18867
18868 break;
18869 }
18870 case ZigTypeIdOpaque:
18871 {
18872 result = g->pass1_arena->create<ZigValue>();
18873 result->special = ConstValSpecialStatic;
18874 result->type = ir_type_info_get_type(ira, "Opaque", nullptr);
18875
18876 ZigValue **fields = alloc_const_vals_ptrs(g, 1);
18877 result->data.x_struct.fields = fields;
18878
18879 // decls: []Type.Declaration
18880 ensure_field_index(result->type, "decls", 0);
18881 if ((err = ir_make_type_info_decls(ira, source_node, fields[0],
18882 type_entry->data.opaque.decls_scope, false)))
18883 {
18884 return err;
18885 }
18886
18887 break;
18888 }
18889 case ZigTypeIdFnFrame:
18890 {
18891 result = g->pass1_arena->create<ZigValue>();
18892 result->special = ConstValSpecialStatic;
18893 result->type = ir_type_info_get_type(ira, "Frame", nullptr);
18894 ZigValue **fields = alloc_const_vals_ptrs(g, 1);
18895 result->data.x_struct.fields = fields;
18896 ZigFn *fn = type_entry->data.frame.fn;
18897 // function: ?*const anyopaque
18898 ensure_field_index(result->type, "function", 0);
18899 fields[0]->special = ConstValSpecialStatic;
18900 fields[0]->type = get_pointer_to_type(g, g->builtin_types.entry_anyopaque, true);
18901 fields[0]->data.x_ptr.special = ConstPtrSpecialFunction;
18902 fields[0]->data.x_ptr.data.fn.fn_entry = fn;
18903 break;
18904 }
18905 }
18906
18907 assert(result != nullptr);
18908 g->type_info_cache.put(type_entry, result);
18909 *out = result;
18910 return ErrorNone;
18911}
18912
18913static Stage1AirInst *ir_analyze_instruction_type_info(IrAnalyze *ira, Stage1ZirInstTypeInfo *instruction) {
18914 Error err;
18915 Stage1AirInst *type_value = instruction->type_value->child;
18916 ZigType *type_entry = ir_resolve_type(ira, type_value);
18917 if (type_is_invalid(type_entry))
18918 return ira->codegen->invalid_inst_gen;
18919
18920 ZigType *result_type = ir_type_info_get_type(ira, nullptr, nullptr);
18921
18922 ZigValue *payload;
18923 if ((err = ir_make_type_info_value(ira, instruction->base.scope, instruction->base.source_node, type_entry, &payload)))
18924 return ira->codegen->invalid_inst_gen;
18925
18926 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, result_type);
18927 ZigValue *out_val = result->value;
18928 bigint_init_unsigned(&out_val->data.x_union.tag, type_id_index(type_entry));
18929 out_val->data.x_union.payload = payload;
18930
18931 if (payload != nullptr) {
18932 payload->parent.id = ConstParentIdUnion;
18933 payload->parent.data.p_union.union_val = out_val;
18934 }
18935
18936 return result;
18937}
18938
18939static ZigValue *get_const_field(IrAnalyze *ira, AstNode *source_node, ZigValue *struct_value,
18940 const char *name, size_t field_index)
18941{
18942 Error err;
18943 ensure_field_index(struct_value->type, name, field_index);
18944 TypeStructField *field = struct_value->type->data.structure.fields[field_index];
18945 ZigValue *val = field->is_comptime ? field->init_val :
18946 struct_value->data.x_struct.fields[field_index];
18947 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, source_node, val, UndefBad)))
18948 return nullptr;
18949 return val;
18950}
18951
18952static Error get_const_field_sentinel(IrAnalyze *ira, Scope *scope, AstNode *source_node,
18953 ZigValue *struct_value, const char *name, size_t field_index, ZigType *elem_type,
18954 ZigValue **result)
18955{
18956 ZigValue *field_val = get_const_field(ira, source_node, struct_value, name, field_index);
18957 if (field_val == nullptr)
18958 return ErrorSemanticAnalyzeFail;
18959
18960 // type of `field_val` is `?*const anyopaque`.
18961 if (field_val->data.x_ptr.special == ConstPtrSpecialNull) {
18962 *result = nullptr;
18963 return ErrorNone;
18964 }
18965
18966 ZigValue *pointee = const_ptr_pointee_unchecked_no_isf(ira->codegen, field_val);
18967 if (pointee == nullptr)
18968 return ErrorSemanticAnalyzeFail;
18969
18970 *result = pointee;
18971 return ErrorNone;
18972}
18973
18974static Error get_const_field_bool(IrAnalyze *ira, AstNode *source_node, ZigValue *struct_value,
18975 const char *name, size_t field_index, bool *out)
18976{
18977 ZigValue *value = get_const_field(ira, source_node, struct_value, name, field_index);
18978 if (value == nullptr)
18979 return ErrorSemanticAnalyzeFail;
18980 assert(value->type == ira->codegen->builtin_types.entry_bool);
18981 *out = value->data.x_bool;
18982 return ErrorNone;
18983}
18984
18985static BigInt *get_const_field_lit_int(IrAnalyze *ira, AstNode *source_node, ZigValue *struct_value, const char *name, size_t field_index)
18986{
18987 ZigValue *value = get_const_field(ira, source_node, struct_value, name, field_index);
18988 if (value == nullptr)
18989 return nullptr;
18990 assert(value->type == ira->codegen->builtin_types.entry_num_lit_int);
18991 return &value->data.x_bigint;
18992}
18993
18994static ZigType *get_const_field_meta_type(IrAnalyze *ira, AstNode *source_node, ZigValue *struct_value, const char *name, size_t field_index)
18995{
18996 ZigValue *value = get_const_field(ira, source_node, struct_value, name, field_index);
18997 if (value == nullptr)
18998 return ira->codegen->invalid_inst_gen->value->type;
18999 assert(value->type == ira->codegen->builtin_types.entry_type);
19000 return value->data.x_type;
19001}
19002
19003static ZigType *get_const_field_meta_type_optional(IrAnalyze *ira, AstNode *source_node,
19004 ZigValue *struct_value, const char *name, size_t field_index)
19005{
19006 ZigValue *value = get_const_field(ira, source_node, struct_value, name, field_index);
19007 if (value == nullptr)
19008 return ira->codegen->invalid_inst_gen->value->type;
19009 assert(value->type->id == ZigTypeIdOptional);
19010 assert(value->type->data.maybe.child_type == ira->codegen->builtin_types.entry_type);
19011 if (value->data.x_optional == nullptr)
19012 return nullptr;
19013 return value->data.x_optional->data.x_type;
19014}
19015
19016static Error get_const_field_buf(IrAnalyze *ira, AstNode *source_node, ZigValue *struct_value,
19017 const char *name, size_t field_index, Buf *out)
19018{
19019 ZigValue *slice = get_const_field(ira, source_node, struct_value, name, field_index);
19020 ZigValue *ptr = slice->data.x_struct.fields[slice_ptr_index];
19021 ZigValue *len = slice->data.x_struct.fields[slice_len_index];
19022 assert(ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
19023 ZigValue *arr = ptr->data.x_ptr.data.base_array.array_val;
19024 assert(arr->special == ConstValSpecialStatic);
19025
19026 const size_t start_value = ptr->data.x_ptr.data.base_array.elem_index;
19027 const size_t len_value = bigint_as_usize(&len->data.x_bigint);
19028
19029 switch (arr->data.x_array.special) {
19030 case ConstArraySpecialUndef:
19031 return ErrorSemanticAnalyzeFail;
19032 case ConstArraySpecialNone: {
19033 assert(start_value <= arr->type->data.array.len);
19034 assert(start_value + len_value <= arr->type->data.array.len);
19035 buf_resize(out, 0);
19036 for (size_t j = 0; j < len_value; j++) {
19037 ZigValue *ch_val = &arr->data.x_array.data.s_none.elements[start_value + j];
19038 unsigned ch = bigint_as_u32(&ch_val->data.x_bigint);
19039 buf_append_char(out, ch);
19040 }
19041 break;
19042 }
19043 case ConstArraySpecialBuf:
19044 assert(start_value <= buf_len(arr->data.x_array.data.s_buf));
19045 assert(start_value + len_value <= buf_len(arr->data.x_array.data.s_buf));
19046 buf_init_from_mem(out, buf_ptr(arr->data.x_array.data.s_buf) + start_value, len_value);
19047 break;
19048 }
19049 return ErrorNone;
19050}
19051
19052static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigTypeId tagTypeId, ZigValue *payload) {
19053 Error err;
19054 switch (tagTypeId) {
19055 case ZigTypeIdInvalid:
19056 zig_unreachable();
19057 case ZigTypeIdMetaType:
19058 return ira->codegen->builtin_types.entry_type;
19059 case ZigTypeIdVoid:
19060 return ira->codegen->builtin_types.entry_void;
19061 case ZigTypeIdBool:
19062 return ira->codegen->builtin_types.entry_bool;
19063 case ZigTypeIdUnreachable:
19064 return ira->codegen->builtin_types.entry_unreachable;
19065 case ZigTypeIdComptimeFloat:
19066 return ira->codegen->builtin_types.entry_num_lit_float;
19067 case ZigTypeIdComptimeInt:
19068 return ira->codegen->builtin_types.entry_num_lit_int;
19069 case ZigTypeIdUndefined:
19070 return ira->codegen->builtin_types.entry_undef;
19071 case ZigTypeIdNull:
19072 return ira->codegen->builtin_types.entry_null;
19073 case ZigTypeIdEnumLiteral:
19074 return ira->codegen->builtin_types.entry_enum_literal;
19075 default:
19076 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, source_node, payload, UndefBad)))
19077 return ira->codegen->invalid_inst_gen->value->type;
19078 }
19079 switch (tagTypeId) {
19080 case ZigTypeIdInvalid:
19081 case ZigTypeIdMetaType:
19082 case ZigTypeIdVoid:
19083 case ZigTypeIdBool:
19084 case ZigTypeIdUnreachable:
19085 case ZigTypeIdComptimeFloat:
19086 case ZigTypeIdComptimeInt:
19087 case ZigTypeIdUndefined:
19088 case ZigTypeIdNull:
19089 case ZigTypeIdEnumLiteral:
19090 zig_unreachable();
19091 case ZigTypeIdInt: {
19092 assert(payload->special == ConstValSpecialStatic);
19093 assert(payload->type == ir_type_info_get_type(ira, "Int", nullptr));
19094 BigInt *bi = get_const_field_lit_int(ira, source_node, payload, "bits", 1);
19095 if (bi == nullptr)
19096 return ira->codegen->invalid_inst_gen->value->type;
19097 ZigValue *value = get_const_field(ira, source_node, payload, "signedness", 0);
19098 if (value == nullptr)
19099 return ira->codegen->invalid_inst_gen->value->type;
19100 assert(value->type == get_builtin_type(ira->codegen, "Signedness"));
19101 bool is_signed = !bigint_as_u32(&value->data.x_enum_tag);
19102 return get_int_type(ira->codegen, is_signed, bigint_as_u32(bi));
19103 }
19104 case ZigTypeIdFloat:
19105 {
19106 assert(payload->special == ConstValSpecialStatic);
19107 assert(payload->type == ir_type_info_get_type(ira, "Float", nullptr));
19108 BigInt *bi = get_const_field_lit_int(ira, source_node, payload, "bits", 0);
19109 if (bi == nullptr)
19110 return ira->codegen->invalid_inst_gen->value->type;
19111 uint32_t bits = bigint_as_u32(bi);
19112 switch (bits) {
19113 case 16: return ira->codegen->builtin_types.entry_f16;
19114 case 32: return ira->codegen->builtin_types.entry_f32;
19115 case 64: return ira->codegen->builtin_types.entry_f64;
19116 case 80: return ira->codegen->builtin_types.entry_f80;
19117 case 128: return ira->codegen->builtin_types.entry_f128;
19118 }
19119 ir_add_error_node(ira, source_node, buf_sprintf("%d-bit float unsupported", bits));
19120 return ira->codegen->invalid_inst_gen->value->type;
19121 }
19122 case ZigTypeIdPointer:
19123 {
19124 ZigType *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer", nullptr);
19125 assert(payload->special == ConstValSpecialStatic);
19126 assert(payload->type == type_info_pointer_type);
19127 ZigValue *size_value = get_const_field(ira, source_node, payload, "size", 0);
19128 if (size_value == nullptr)
19129 return ira->codegen->invalid_inst_gen->value->type;
19130
19131 assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type));
19132 BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag);
19133 PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index);
19134 ZigType *elem_type = get_const_field_meta_type(ira, source_node, payload, "child", 5);
19135 if (type_is_invalid(elem_type))
19136 return ira->codegen->invalid_inst_gen->value->type;
19137 ZigValue *sentinel;
19138 if ((err = get_const_field_sentinel(ira, scope, source_node, payload, "sentinel", 7,
19139 elem_type, &sentinel)))
19140 {
19141 return ira->codegen->invalid_inst_gen->value->type;
19142 }
19143 if (sentinel != nullptr && (size_enum_index == BuiltinPtrSizeOne || size_enum_index == BuiltinPtrSizeC)) {
19144 ir_add_error_node(ira, source_node,
19145 buf_sprintf("sentinels are only allowed on slices and unknown-length pointers"));
19146 return ira->codegen->invalid_inst_gen->value->type;
19147 }
19148
19149 BigInt *alignment = get_const_field_lit_int(ira, source_node, payload, "alignment", 3);
19150 if (alignment == nullptr)
19151 return ira->codegen->invalid_inst_gen->value->type;
19152
19153 ZigValue *as_value = get_const_field(ira, source_node, payload, "address_space", 4);
19154 if (as_value == nullptr)
19155 return ira->codegen->invalid_inst_gen->value->type;
19156 assert(as_value->special == ConstValSpecialStatic);
19157 assert(as_value->type == get_builtin_type(ira->codegen, "AddressSpace"));
19158 AddressSpace as = (AddressSpace)bigint_as_u32(&as_value->data.x_enum_tag);
19159 if (as != AddressSpaceGeneric) {
19160 ir_add_error_node(ira, source_node, buf_sprintf(
19161 "address space '%s' not available in stage 1 compiler, must be .generic",
19162 address_space_name(as)));
19163 return ira->codegen->invalid_inst_gen->value->type;
19164 }
19165
19166 bool is_const;
19167 if ((err = get_const_field_bool(ira, source_node, payload, "is_const", 1, &is_const)))
19168 return ira->codegen->invalid_inst_gen->value->type;
19169
19170 bool is_volatile;
19171 if ((err = get_const_field_bool(ira, source_node, payload, "is_volatile", 2,
19172 &is_volatile)))
19173 {
19174 return ira->codegen->invalid_inst_gen->value->type;
19175 }
19176
19177 bool is_allowzero;
19178 if ((err = get_const_field_bool(ira, source_node, payload, "is_allowzero", 6,
19179 &is_allowzero)))
19180 {
19181 return ira->codegen->invalid_inst_gen->value->type;
19182 }
19183
19184 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusAlignmentKnown))) {
19185 return ira->codegen->invalid_inst_gen->value->type;
19186 }
19187
19188 ZigType *ptr_type = get_pointer_to_type_extra2(ira->codegen,
19189 elem_type,
19190 is_const,
19191 is_volatile,
19192 ptr_len,
19193 bigint_as_u32(alignment),
19194 0, // bit_offset_in_host
19195 0, // host_int_bytes
19196 is_allowzero,
19197 VECTOR_INDEX_NONE, nullptr, sentinel);
19198 if (size_enum_index != BuiltinPtrSizeSlice)
19199 return ptr_type;
19200 return get_slice_type(ira->codegen, ptr_type);
19201 }
19202 case ZigTypeIdArray: {
19203 assert(payload->special == ConstValSpecialStatic);
19204 assert(payload->type == ir_type_info_get_type(ira, "Array", nullptr));
19205 ZigType *elem_type = get_const_field_meta_type(ira, source_node, payload, "child", 1);
19206 if (type_is_invalid(elem_type))
19207 return ira->codegen->invalid_inst_gen->value->type;
19208 ZigValue *sentinel;
19209 if ((err = get_const_field_sentinel(ira, scope, source_node, payload, "sentinel", 2,
19210 elem_type, &sentinel)))
19211 {
19212 return ira->codegen->invalid_inst_gen->value->type;
19213 }
19214 BigInt *bi = get_const_field_lit_int(ira, source_node, payload, "len", 0);
19215 if (bi == nullptr)
19216 return ira->codegen->invalid_inst_gen->value->type;
19217 return get_array_type(ira->codegen, elem_type, bigint_as_u64(bi), sentinel);
19218 }
19219 case ZigTypeIdOptional: {
19220 assert(payload->special == ConstValSpecialStatic);
19221 assert(payload->type == ir_type_info_get_type(ira, "Optional", nullptr));
19222 ZigType *child_type = get_const_field_meta_type(ira, source_node, payload, "child", 0);
19223 if (type_is_invalid(child_type))
19224 return ira->codegen->invalid_inst_gen->value->type;
19225 return get_optional_type(ira->codegen, child_type);
19226 }
19227 case ZigTypeIdErrorUnion: {
19228 assert(payload->special == ConstValSpecialStatic);
19229 assert(payload->type == ir_type_info_get_type(ira, "ErrorUnion", nullptr));
19230 ZigType *err_set_type = get_const_field_meta_type(ira, source_node, payload, "error_set", 0);
19231 if (type_is_invalid(err_set_type))
19232 return ira->codegen->invalid_inst_gen->value->type;
19233
19234 ZigType *payload_type = get_const_field_meta_type(ira, source_node, payload, "payload", 1);
19235 if (type_is_invalid(payload_type))
19236 return ira->codegen->invalid_inst_gen->value->type;
19237
19238 return get_error_union_type(ira->codegen, err_set_type, payload_type);
19239 }
19240 case ZigTypeIdOpaque: {
19241 assert(payload->special == ConstValSpecialStatic);
19242 assert(payload->type == ir_type_info_get_type(ira, "Opaque", nullptr));
19243
19244 ZigValue *decls_value = get_const_field(ira, source_node, payload, "decls", 0);
19245 if (decls_value == nullptr)
19246 return ira->codegen->invalid_inst_gen->value->type;
19247 assert(decls_value->special == ConstValSpecialStatic);
19248 assert(is_slice(decls_value->type));
19249 ZigValue *decls_len_value = decls_value->data.x_struct.fields[slice_len_index];
19250 size_t decls_len = bigint_as_usize(&decls_len_value->data.x_bigint);
19251 if (decls_len != 0) {
19252 ir_add_error_node(ira, source_node, buf_create_from_str("Type.Struct.decls must be empty for @Type"));
19253 return ira->codegen->invalid_inst_gen->value->type;
19254 }
19255
19256 Buf *bare_name = buf_alloc();
19257 Buf *full_name = get_anon_type_name(ira->codegen,
19258 ira->zir, "opaque", scope, source_node, bare_name, nullptr);
19259 return get_opaque_type(ira->codegen,
19260 scope, source_node, buf_ptr(full_name), bare_name);
19261 }
19262 case ZigTypeIdVector: {
19263 assert(payload->special == ConstValSpecialStatic);
19264 assert(payload->type == ir_type_info_get_type(ira, "Vector", nullptr));
19265 BigInt *len = get_const_field_lit_int(ira, source_node, payload, "len", 0);
19266 if (len == nullptr)
19267 return ira->codegen->invalid_inst_gen->value->type;
19268
19269 ZigType *child_type = get_const_field_meta_type(ira, source_node, payload, "child", 1);
19270 if ((err = ir_validate_vector_elem_type(ira, source_node, child_type))) {
19271 return ira->codegen->invalid_inst_gen->value->type;
19272 }
19273 return get_vector_type(ira->codegen, bigint_as_u32(len), child_type);
19274 }
19275 case ZigTypeIdAnyFrame: {
19276 assert(payload->special == ConstValSpecialStatic);
19277 assert(payload->type == ir_type_info_get_type(ira, "AnyFrame", nullptr));
19278 ZigType *child_type = get_const_field_meta_type_optional(ira, source_node, payload, "child", 0);
19279 if (child_type != nullptr && type_is_invalid(child_type))
19280 return ira->codegen->invalid_inst_gen->value->type;
19281
19282 return get_any_frame_type(ira->codegen, child_type);
19283 }
19284 case ZigTypeIdFnFrame: {
19285 ir_add_error_node(ira, source_node,
19286 buf_sprintf("use the @Frame builtin instead of @Type"));
19287 return ira->codegen->invalid_inst_gen->value->type;
19288 }
19289 case ZigTypeIdErrorSet: {
19290 assert(payload->special == ConstValSpecialStatic);
19291 assert(payload->type->id == ZigTypeIdOptional);
19292 ZigValue *slice = payload->data.x_optional;
19293 if (slice == nullptr)
19294 return ira->codegen->builtin_types.entry_global_error_set;
19295 assert(slice->special == ConstValSpecialStatic);
19296 assert(is_slice(slice->type));
19297 ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
19298 Buf bare_name = BUF_INIT;
19299 buf_init_from_buf(&err_set_type->name,
19300 get_anon_type_name(ira->codegen, ira->zir, "error", scope, source_node, &bare_name, nullptr));
19301 err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits;
19302 err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align;
19303 err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size;
19304 ZigValue *ptr = slice->data.x_struct.fields[slice_ptr_index];
19305 assert(ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);;
19306 assert(ptr->data.x_ptr.data.base_array.elem_index == 0);
19307 ZigValue *arr = ptr->data.x_ptr.data.base_array.array_val;
19308 assert(arr->special == ConstValSpecialStatic);
19309 assert(arr->data.x_array.special == ConstArraySpecialNone);
19310 ZigValue *len = slice->data.x_struct.fields[slice_len_index];
19311 size_t count = bigint_as_usize(&len->data.x_bigint);
19312 err_set_type->data.error_set.err_count = count;
19313 err_set_type->data.error_set.errors = heap::c_allocator.allocate<ErrorTableEntry *>(count);
19314 bool *already_set = heap::c_allocator.allocate<bool>(ira->codegen->errors_by_index.length + count);
19315 for (size_t i = 0; i < count; i++) {
19316 ZigValue *error = &arr->data.x_array.data.s_none.elements[i];
19317 assert(error->type == ir_type_info_get_type(ira, "Error", nullptr));
19318 ErrorTableEntry *err_entry = heap::c_allocator.create<ErrorTableEntry>();
19319 err_entry->decl_node = source_node;
19320 if ((err = get_const_field_buf(ira, source_node, error, "name", 0, &err_entry->name)))
19321 return ira->codegen->invalid_inst_gen->value->type;
19322 auto existing_entry = ira->codegen->error_table.put_unique(&err_entry->name, err_entry);
19323 if (existing_entry) {
19324 err_entry->value = existing_entry->value->value;
19325 } else {
19326 size_t error_value_count = ira->codegen->errors_by_index.length;
19327 assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)ira->codegen->err_tag_type->data.integral.bit_count));
19328 err_entry->value = error_value_count;
19329 ira->codegen->errors_by_index.append(err_entry);
19330 }
19331 if (already_set[err_entry->value]) {
19332 ir_add_error_node(ira, source_node, buf_sprintf("duplicate error: %s", buf_ptr(&err_entry->name)));
19333 return ira->codegen->invalid_inst_gen->value->type;
19334 } else {
19335 already_set[err_entry->value] = true;
19336 }
19337 err_set_type->data.error_set.errors[i] = err_entry;
19338 }
19339 return err_set_type;
19340 }
19341 case ZigTypeIdStruct: {
19342 assert(payload->special == ConstValSpecialStatic);
19343 assert(payload->type == ir_type_info_get_type(ira, "Struct", nullptr));
19344
19345 ZigValue *layout_value = get_const_field(ira, source_node, payload, "layout", 0);
19346 if (layout_value == nullptr)
19347 return ira->codegen->invalid_inst_gen->value->type;
19348 assert(layout_value->special == ConstValSpecialStatic);
19349 assert(layout_value->type == ir_type_info_get_type(ira, "ContainerLayout", nullptr));
19350 ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag);
19351
19352 ZigType *tag_type = get_const_field_meta_type_optional(ira, source_node, payload, "backing_integer", 1);
19353 if (tag_type != nullptr) {
19354 ir_add_error_node(ira, source_node, buf_create_from_str(
19355 "the stage1 compiler does not support explicit backing integer types on packed structs"));
19356 return ira->codegen->invalid_inst_gen->value->type;
19357 }
19358
19359 ZigValue *fields_value = get_const_field(ira, source_node, payload, "fields", 2);
19360 if (fields_value == nullptr)
19361 return ira->codegen->invalid_inst_gen->value->type;
19362 assert(fields_value->special == ConstValSpecialStatic);
19363 assert(is_slice(fields_value->type));
19364 ZigValue *fields_ptr = fields_value->data.x_struct.fields[slice_ptr_index];
19365 ZigValue *fields_len_value = fields_value->data.x_struct.fields[slice_len_index];
19366 size_t fields_len = bigint_as_usize(&fields_len_value->data.x_bigint);
19367
19368 ZigValue *decls_value = get_const_field(ira, source_node, payload, "decls", 3);
19369 if (decls_value == nullptr)
19370 return ira->codegen->invalid_inst_gen->value->type;
19371 assert(decls_value->special == ConstValSpecialStatic);
19372 assert(is_slice(decls_value->type));
19373 ZigValue *decls_len_value = decls_value->data.x_struct.fields[slice_len_index];
19374 size_t decls_len = bigint_as_usize(&decls_len_value->data.x_bigint);
19375 if (decls_len != 0) {
19376 ir_add_error_node(ira, source_node, buf_create_from_str("Type.Struct.decls must be empty for @Type"));
19377 return ira->codegen->invalid_inst_gen->value->type;
19378 }
19379
19380 bool is_tuple;
19381 if ((err = get_const_field_bool(ira, source_node, payload, "is_tuple", 4, &is_tuple)))
19382 return ira->codegen->invalid_inst_gen->value->type;
19383
19384 ZigType *entry = new_type_table_entry(ZigTypeIdStruct);
19385 buf_init_from_buf(&entry->name,
19386 get_anon_type_name(ira->codegen, ira->zir, "struct", scope, source_node, &entry->name, nullptr));
19387 entry->data.structure.decl_node = source_node;
19388 entry->data.structure.fields = alloc_type_struct_fields(fields_len);
19389 entry->data.structure.fields_by_name.init(fields_len);
19390 entry->data.structure.src_field_count = fields_len;
19391 entry->data.structure.layout = layout;
19392 entry->data.structure.special = is_tuple ? StructSpecialInferredTuple : StructSpecialNone;
19393 entry->data.structure.created_by_at_type = true;
19394 entry->data.structure.decls_scope = create_decls_scope(
19395 ira->codegen, source_node, scope, entry, get_scope_import(scope), &entry->name);
19396
19397 assert(fields_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
19398 assert(fields_ptr->data.x_ptr.data.base_array.elem_index == 0);
19399 ZigValue *fields_arr = fields_ptr->data.x_ptr.data.base_array.array_val;
19400 assert(fields_arr->special == ConstValSpecialStatic);
19401 assert(fields_arr->data.x_array.special == ConstArraySpecialNone);
19402 for (size_t i = 0; i < fields_len; i++) {
19403 ZigValue *field_value = &fields_arr->data.x_array.data.s_none.elements[i];
19404 assert(field_value->type == ir_type_info_get_type(ira, "StructField", nullptr));
19405 TypeStructField *field = entry->data.structure.fields[i];
19406 field->name = buf_alloc();
19407 if ((err = get_const_field_buf(ira, source_node, field_value, "name", 0, field->name)))
19408 return ira->codegen->invalid_inst_gen->value->type;
19409 field->decl_node = source_node;
19410 ZigValue *type_value = get_const_field(ira, source_node, field_value, "field_type", 1);
19411 if (type_value == nullptr)
19412 return ira->codegen->invalid_inst_gen->value->type;
19413 field->type_val = type_value;
19414 field->type_entry = type_value->data.x_type;
19415 if (entry->data.structure.fields_by_name.put_unique(field->name, field) != nullptr) {
19416 ir_add_error_node(ira, source_node, buf_sprintf("duplicate struct field '%s'", buf_ptr(field->name)));
19417 return ira->codegen->invalid_inst_gen->value->type;
19418 }
19419 ZigValue *default_value = get_const_field(ira, source_node, field_value, "default_value", 2);
19420 if (default_value == nullptr)
19421 return ira->codegen->invalid_inst_gen->value->type;
19422
19423 // type of `default_value` is `?*const anyopaque`.
19424 if (default_value->data.x_ptr.special == ConstPtrSpecialNull) {
19425 field->init_val = nullptr;
19426 } else {
19427 ZigValue *pointee = const_ptr_pointee_unchecked_no_isf(ira->codegen, default_value);
19428 if (pointee == nullptr)
19429 return ira->codegen->invalid_inst_gen->value->type;
19430 field->init_val = pointee;
19431 }
19432
19433 if ((err = get_const_field_bool(ira, source_node, field_value, "is_comptime", 3, &field->is_comptime)))
19434 return ira->codegen->invalid_inst_gen->value->type;
19435 BigInt *alignment = get_const_field_lit_int(ira, source_node, field_value, "alignment", 4);
19436 if (alignment == nullptr)
19437 return ira->codegen->invalid_inst_gen->value->type;
19438 field->align = bigint_as_u32(alignment);
19439 }
19440
19441 return entry;
19442 }
19443 case ZigTypeIdEnum: {
19444 assert(payload->special == ConstValSpecialStatic);
19445 assert(payload->type == ir_type_info_get_type(ira, "Enum", nullptr));
19446
19447 ZigValue *layout_value = get_const_field(ira, source_node, payload, "layout", 0);
19448 if (layout_value == nullptr)
19449 return ira->codegen->invalid_inst_gen->value->type;
19450
19451 assert(layout_value->special == ConstValSpecialStatic);
19452 assert(layout_value->type == ir_type_info_get_type(ira, "ContainerLayout", nullptr));
19453 ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag);
19454
19455 ZigType *tag_type = get_const_field_meta_type(ira, source_node, payload, "tag_type", 1);
19456 if (type_is_invalid(tag_type))
19457 return ira->codegen->invalid_inst_gen->value->type;
19458 if (tag_type->id != ZigTypeIdInt) {
19459 ir_add_error_node(ira, source_node, buf_sprintf(
19460 "Type.Enum.tag_type must be an integer type, not '%s'", buf_ptr(&tag_type->name)));
19461 return ira->codegen->invalid_inst_gen->value->type;
19462 }
19463
19464 ZigValue *fields_value = get_const_field(ira, source_node, payload, "fields", 2);
19465 if (fields_value == nullptr)
19466 return ira->codegen->invalid_inst_gen->value->type;
19467
19468 assert(fields_value->special == ConstValSpecialStatic);
19469 assert(is_slice(fields_value->type));
19470 ZigValue *fields_ptr = fields_value->data.x_struct.fields[slice_ptr_index];
19471 ZigValue *fields_len_value = fields_value->data.x_struct.fields[slice_len_index];
19472 size_t fields_len = bigint_as_usize(&fields_len_value->data.x_bigint);
19473
19474 ZigValue *decls_value = get_const_field(ira, source_node, payload, "decls", 3);
19475 if (decls_value == nullptr)
19476 return ira->codegen->invalid_inst_gen->value->type;
19477
19478 assert(decls_value->special == ConstValSpecialStatic);
19479 assert(is_slice(decls_value->type));
19480 ZigValue *decls_len_value = decls_value->data.x_struct.fields[slice_len_index];
19481 size_t decls_len = bigint_as_usize(&decls_len_value->data.x_bigint);
19482 if (decls_len != 0) {
19483 ir_add_error_node(ira, source_node, buf_create_from_str("Type.Enum.decls must be empty for @Type"));
19484 return ira->codegen->invalid_inst_gen->value->type;
19485 }
19486
19487 Error err;
19488 bool is_exhaustive;
19489 if ((err = get_const_field_bool(ira, source_node, payload, "is_exhaustive", 4, &is_exhaustive)))
19490 return ira->codegen->invalid_inst_gen->value->type;
19491
19492 ZigType *entry = new_type_table_entry(ZigTypeIdEnum);
19493 buf_init_from_buf(&entry->name,
19494 get_anon_type_name(ira->codegen, ira->zir, "enum", scope, source_node, &entry->name, nullptr));
19495 entry->data.enumeration.decl_node = source_node;
19496 entry->data.enumeration.tag_int_type = tag_type;
19497 entry->data.enumeration.decls_scope = create_decls_scope(
19498 ira->codegen, source_node, scope, entry, get_scope_import(scope), &entry->name);
19499 entry->data.enumeration.fields = heap::c_allocator.allocate<TypeEnumField>(fields_len);
19500 entry->data.enumeration.fields_by_name.init(fields_len);
19501 entry->data.enumeration.src_field_count = fields_len;
19502 entry->data.enumeration.layout = layout;
19503 entry->data.enumeration.non_exhaustive = !is_exhaustive;
19504
19505 assert(fields_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
19506 assert(fields_ptr->data.x_ptr.data.base_array.elem_index == 0);
19507 ZigValue *fields_arr = fields_ptr->data.x_ptr.data.base_array.array_val;
19508 assert(fields_arr->special == ConstValSpecialStatic);
19509 assert(fields_arr->data.x_array.special == ConstArraySpecialNone);
19510 for (size_t i = 0; i < fields_len; i++) {
19511 ZigValue *field_value = &fields_arr->data.x_array.data.s_none.elements[i];
19512 assert(field_value->type == ir_type_info_get_type(ira, "EnumField", nullptr));
19513 TypeEnumField *field = &entry->data.enumeration.fields[i];
19514 field->name = buf_alloc();
19515 if ((err = get_const_field_buf(ira, source_node, field_value, "name", 0, field->name)))
19516 return ira->codegen->invalid_inst_gen->value->type;
19517 field->decl_index = i;
19518 field->decl_node = source_node;
19519 if (entry->data.enumeration.fields_by_name.put_unique(field->name, field) != nullptr) {
19520 ir_add_error_node(ira, source_node, buf_sprintf("duplicate enum field '%s'", buf_ptr(field->name)));
19521 return ira->codegen->invalid_inst_gen->value->type;
19522 }
19523 BigInt *field_int_value = get_const_field_lit_int(ira, source_node, field_value, "value", 1);
19524 if (field_int_value == nullptr)
19525 return ira->codegen->invalid_inst_gen->value->type;
19526 field->value = *field_int_value;
19527 }
19528 return entry;
19529 }
19530 case ZigTypeIdUnion: {
19531 assert(payload->special == ConstValSpecialStatic);
19532 assert(payload->type == ir_type_info_get_type(ira, "Union", nullptr));
19533
19534 ZigValue *layout_value = get_const_field(ira, source_node, payload, "layout", 0);
19535 if (layout_value == nullptr)
19536 return ira->codegen->invalid_inst_gen->value->type;
19537 assert(layout_value->special == ConstValSpecialStatic);
19538 assert(layout_value->type == ir_type_info_get_type(ira, "ContainerLayout", nullptr));
19539 ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag);
19540
19541 ZigType *tag_type = get_const_field_meta_type_optional(ira, source_node, payload, "tag_type", 1);
19542 if (tag_type != nullptr && type_is_invalid(tag_type)) {
19543 return ira->codegen->invalid_inst_gen->value->type;
19544 }
19545 if (tag_type != nullptr && tag_type->id != ZigTypeIdEnum) {
19546 ir_add_error_node(ira, source_node, buf_sprintf(
19547 "expected enum type, found '%s'", type_id_name(tag_type->id)));
19548 return ira->codegen->invalid_inst_gen->value->type;
19549 }
19550
19551 ZigValue *fields_value = get_const_field(ira, source_node, payload, "fields", 2);
19552 if (fields_value == nullptr)
19553 return ira->codegen->invalid_inst_gen->value->type;
19554
19555 assert(fields_value->special == ConstValSpecialStatic);
19556 assert(is_slice(fields_value->type));
19557 ZigValue *fields_ptr = fields_value->data.x_struct.fields[slice_ptr_index];
19558 ZigValue *fields_len_value = fields_value->data.x_struct.fields[slice_len_index];
19559 size_t fields_len = bigint_as_usize(&fields_len_value->data.x_bigint);
19560
19561 ZigValue *decls_value = get_const_field(ira, source_node, payload, "decls", 3);
19562 if (decls_value == nullptr)
19563 return ira->codegen->invalid_inst_gen->value->type;
19564
19565 assert(decls_value->special == ConstValSpecialStatic);
19566 assert(is_slice(decls_value->type));
19567 ZigValue *decls_len_value = decls_value->data.x_struct.fields[slice_len_index];
19568 size_t decls_len = bigint_as_usize(&decls_len_value->data.x_bigint);
19569 if (decls_len != 0) {
19570 ir_add_error_node(ira, source_node, buf_create_from_str("Type.Union.decls must be empty for @Type"));
19571 return ira->codegen->invalid_inst_gen->value->type;
19572 }
19573
19574 ZigType *entry = new_type_table_entry(ZigTypeIdUnion);
19575 buf_init_from_buf(&entry->name,
19576 get_anon_type_name(ira->codegen, ira->zir, "union", scope, source_node, &entry->name, nullptr));
19577 entry->data.unionation.decl_node = source_node;
19578 entry->data.unionation.fields = heap::c_allocator.allocate<TypeUnionField>(fields_len);
19579 entry->data.unionation.fields_by_name.init(fields_len);
19580 entry->data.unionation.decls_scope = create_decls_scope(
19581 ira->codegen, source_node, scope, entry, get_scope_import(scope), &entry->name);
19582 entry->data.unionation.tag_type = tag_type;
19583 entry->data.unionation.src_field_count = fields_len;
19584 entry->data.unionation.layout = layout;
19585
19586 assert(fields_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
19587 assert(fields_ptr->data.x_ptr.data.base_array.elem_index == 0);
19588 ZigValue *fields_arr = fields_ptr->data.x_ptr.data.base_array.array_val;
19589 assert(fields_arr->special == ConstValSpecialStatic);
19590 assert(fields_arr->data.x_array.special == ConstArraySpecialNone);
19591 for (size_t i = 0; i < fields_len; i++) {
19592 ZigValue *field_value = &fields_arr->data.x_array.data.s_none.elements[i];
19593 assert(field_value->type == ir_type_info_get_type(ira, "UnionField", nullptr));
19594 TypeUnionField *field = &entry->data.unionation.fields[i];
19595 field->name = buf_alloc();
19596 if ((err = get_const_field_buf(ira, source_node, field_value, "name", 0, field->name)))
19597 return ira->codegen->invalid_inst_gen->value->type;
19598 if (entry->data.unionation.fields_by_name.put_unique(field->name, field) != nullptr) {
19599 ir_add_error_node(ira, source_node, buf_sprintf("duplicate union field '%s'", buf_ptr(field->name)));
19600 return ira->codegen->invalid_inst_gen->value->type;
19601 }
19602 field->decl_node = source_node;
19603 ZigValue *type_value = get_const_field(ira, source_node, field_value, "field_type", 1);
19604 if (type_value == nullptr)
19605 return ira->codegen->invalid_inst_gen->value->type;
19606 field->type_val = type_value;
19607 field->type_entry = type_value->data.x_type;
19608 BigInt *alignment = get_const_field_lit_int(ira, source_node, field_value, "alignment", 2);
19609 if (alignment == nullptr)
19610 return ira->codegen->invalid_inst_gen->value->type;
19611 field->align = bigint_as_u32(alignment);
19612 }
19613 return entry;
19614 }
19615 case ZigTypeIdFn:
19616 case ZigTypeIdBoundFn: {
19617 assert(payload->special == ConstValSpecialStatic);
19618 assert(payload->type == ir_type_info_get_type(ira, "Fn", nullptr));
19619
19620 ZigValue *cc_value = get_const_field(ira, source_node, payload, "calling_convention", 0);
19621 if (cc_value == nullptr)
19622 return ira->codegen->invalid_inst_gen->value->type;
19623 assert(cc_value->special == ConstValSpecialStatic);
19624 assert(cc_value->type == get_builtin_type(ira->codegen, "CallingConvention"));
19625 CallingConvention cc = (CallingConvention)bigint_as_u32(&cc_value->data.x_enum_tag);
19626
19627 BigInt *alignment = get_const_field_lit_int(ira, source_node, payload, "alignment", 1);
19628 if (alignment == nullptr)
19629 return ira->codegen->invalid_inst_gen->value->type;
19630
19631 Error err;
19632 bool is_generic;
19633 if ((err = get_const_field_bool(ira, source_node, payload, "is_generic", 2, &is_generic)))
19634 return ira->codegen->invalid_inst_gen->value->type;
19635 if (is_generic) {
19636 ir_add_error_node(ira, source_node, buf_sprintf("Type.Fn.is_generic must be false for @Type"));
19637 return ira->codegen->invalid_inst_gen->value->type;
19638 }
19639
19640 bool is_var_args;
19641 if ((err = get_const_field_bool(ira, source_node, payload, "is_var_args", 3, &is_var_args)))
19642 return ira->codegen->invalid_inst_gen->value->type;
19643 if (is_var_args && cc != CallingConventionC) {
19644 ir_add_error_node(ira, source_node, buf_sprintf("varargs functions must have C calling convention"));
19645 return ira->codegen->invalid_inst_gen->value->type;
19646 }
19647
19648 ZigType *return_type = get_const_field_meta_type_optional(ira, source_node, payload, "return_type", 4);
19649 if (return_type == nullptr) {
19650 ir_add_error_node(ira, source_node, buf_sprintf("Type.Fn.return_type must be non-null for @Type"));
19651 return ira->codegen->invalid_inst_gen->value->type;
19652 }
19653
19654 ZigValue *args_value = get_const_field(ira, source_node, payload, "args", 5);
19655 if (args_value == nullptr)
19656 return ira->codegen->invalid_inst_gen->value->type;
19657 assert(args_value->special == ConstValSpecialStatic);
19658 assert(is_slice(args_value->type));
19659 ZigValue *args_ptr = args_value->data.x_struct.fields[slice_ptr_index];
19660 ZigValue *args_len_value = args_value->data.x_struct.fields[slice_len_index];
19661 size_t args_len = bigint_as_usize(&args_len_value->data.x_bigint);
19662
19663 FnTypeId fn_type_id = {};
19664 fn_type_id.return_type = return_type;
19665 fn_type_id.param_info = heap::c_allocator.allocate<FnTypeParamInfo>(args_len);
19666 fn_type_id.param_count = args_len;
19667 fn_type_id.next_param_index = args_len;
19668 fn_type_id.is_var_args = is_var_args;
19669 fn_type_id.cc = cc;
19670 fn_type_id.alignment = bigint_as_u32(alignment);
19671
19672 assert(args_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
19673 assert(args_ptr->data.x_ptr.data.base_array.elem_index == 0);
19674 ZigValue *args_arr = args_ptr->data.x_ptr.data.base_array.array_val;
19675 assert(args_arr->special == ConstValSpecialStatic);
19676 assert(args_arr->data.x_array.special == ConstArraySpecialNone);
19677 for (size_t i = 0; i < args_len; i++) {
19678 ZigValue *arg_value = &args_arr->data.x_array.data.s_none.elements[i];
19679 FnTypeParamInfo *info = &fn_type_id.param_info[i];
19680 Error err;
19681 bool is_generic;
19682 if ((err = get_const_field_bool(ira, source_node, arg_value, "is_generic", 0, &is_generic)))
19683 return ira->codegen->invalid_inst_gen->value->type;
19684 if (is_generic) {
19685 ir_add_error_node(ira, source_node, buf_sprintf("Type.Fn.Param.is_generic must be false for @Type"));
19686 return ira->codegen->invalid_inst_gen->value->type;
19687 }
19688 if ((err = get_const_field_bool(ira, source_node, arg_value, "is_noalias", 1, &info->is_noalias)))
19689 return ira->codegen->invalid_inst_gen->value->type;
19690 ZigType *type = get_const_field_meta_type_optional(
19691 ira, source_node, arg_value, "arg_type", 2);
19692 if (type == nullptr) {
19693 ir_add_error_node(ira, source_node, buf_sprintf("Type.Fn.Param.arg_type must be non-null for @Type"));
19694 return ira->codegen->invalid_inst_gen->value->type;
19695 }
19696 info->type = type;
19697 }
19698
19699 ZigType *entry = get_fn_type(ira->codegen, &fn_type_id);
19700
19701 switch (tagTypeId) {
19702 case ZigTypeIdFn:
19703 return entry;
19704 case ZigTypeIdBoundFn: {
19705 ZigType *bound_fn_entry = new_type_table_entry(ZigTypeIdBoundFn);
19706 bound_fn_entry->name = *buf_sprintf("(bound %s)", buf_ptr(&entry->name));
19707 bound_fn_entry->data.bound_fn.fn_type = entry;
19708 return bound_fn_entry;
19709 }
19710 default:
19711 zig_unreachable();
19712 }
19713 }
19714 }
19715 zig_unreachable();
19716}
19717
19718static Stage1AirInst *ir_analyze_instruction_type(IrAnalyze *ira, Stage1ZirInstType *instruction) {
19719 Stage1AirInst *uncasted_type_info = instruction->type_info->child;
19720 if (type_is_invalid(uncasted_type_info->value->type))
19721 return ira->codegen->invalid_inst_gen;
19722
19723 Stage1AirInst *type_info = ir_implicit_cast(ira, uncasted_type_info, ir_type_info_get_type(ira, nullptr, nullptr));
19724 if (type_is_invalid(type_info->value->type))
19725 return ira->codegen->invalid_inst_gen;
19726
19727 ZigValue *type_info_val = ir_resolve_const(ira, type_info, UndefBad);
19728 if (type_info_val == nullptr)
19729 return ira->codegen->invalid_inst_gen;
19730 ZigTypeId type_id_tag = type_id_at_index(bigint_as_usize(&type_info_val->data.x_union.tag));
19731 ZigType *type = type_info_to_type(ira, uncasted_type_info->scope,
19732 uncasted_type_info->source_node, type_id_tag, type_info_val->data.x_union.payload);
19733 if (type_is_invalid(type))
19734 return ira->codegen->invalid_inst_gen;
19735 return ir_const_type(ira, instruction->base.scope, instruction->base.source_node, type);
19736}
19737
19738static Stage1AirInst *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira,
19739 Stage1ZirInstSetEvalBranchQuota *instruction)
19740{
19741 uint64_t new_quota;
19742 if (!ir_resolve_unsigned(ira, instruction->new_quota->child, ira->codegen->builtin_types.entry_u32, &new_quota))
19743 return ira->codegen->invalid_inst_gen;
19744
19745 if (new_quota > *ira->backward_branch_quota) {
19746 *ira->backward_branch_quota = new_quota;
19747 }
19748
19749 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
19750}
19751
19752static Stage1AirInst *ir_analyze_instruction_type_name(IrAnalyze *ira, Stage1ZirInstTypeName *instruction) {
19753 Stage1AirInst *type_value = instruction->type_value->child;
19754 ZigType *type_entry = ir_resolve_type(ira, type_value);
19755 if (type_is_invalid(type_entry))
19756 return ira->codegen->invalid_inst_gen;
19757
19758 if (!type_entry->cached_const_name_val) {
19759 type_entry->cached_const_name_val = create_const_str_lit(ira->codegen, type_bare_name(type_entry));
19760 }
19761 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, nullptr);
19762 copy_const_val(ira->codegen, result->value, type_entry->cached_const_name_val);
19763 return result;
19764}
19765
19766static Stage1AirInst *ir_analyze_instruction_c_import(IrAnalyze *ira, Stage1ZirInstCImport *instruction) {
19767 Error err;
19768 AstNode *node = instruction->base.source_node;
19769 assert(node->type == NodeTypeFnCallExpr);
19770 AstNode *block_node = node->data.fn_call_expr.params.at(0);
19771
19772 ScopeCImport *cimport_scope = create_cimport_scope(ira->codegen, node, instruction->base.scope);
19773
19774 // Execute the C import block like an inline function
19775 ZigType *void_type = ira->codegen->builtin_types.entry_void;
19776 ZigValue *cimport_result;
19777 ZigValue *result_ptr;
19778 create_result_ptr(ira->codegen, void_type, &cimport_result, &result_ptr);
19779 if ((err = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, result_ptr,
19780 ira->backward_branch_count, ira->backward_branch_quota, nullptr,
19781 &cimport_scope->buf, block_node, nullptr, nullptr, nullptr, UndefBad)))
19782 {
19783 return ira->codegen->invalid_inst_gen;
19784 }
19785 if (type_is_invalid(cimport_result->type))
19786 return ira->codegen->invalid_inst_gen;
19787
19788 ZigPackage *cur_scope_pkg = scope_package(instruction->base.scope);
19789 RootStruct *root_struct = node->owner->data.structure.root_struct;
19790 TokenLoc tok_loc = root_struct->token_locs[node->main_token];
19791 Buf *namespace_name = buf_sprintf("%s.cimport:%" PRIu32 ":%" PRIu32,
19792 buf_ptr(&cur_scope_pkg->pkg_path), tok_loc.line + 1, tok_loc.column + 1);
19793
19794 ZigPackage *cimport_pkg = new_anonymous_package();
19795 cimport_pkg->package_table.put(buf_create_from_str("builtin"), ira->codegen->compile_var_package);
19796 cimport_pkg->package_table.put(buf_create_from_str("std"), ira->codegen->std_package);
19797 buf_init_from_buf(&cimport_pkg->pkg_path, namespace_name);
19798
19799 const char *out_zig_path_ptr;
19800 size_t out_zig_path_len;
19801 Stage2ErrorMsg *errors_ptr;
19802 size_t errors_len;
19803 if ((err = stage2_cimport(&ira->codegen->stage1,
19804 buf_ptr(&cimport_scope->buf), buf_len(&cimport_scope->buf),
19805 &out_zig_path_ptr, &out_zig_path_len,
19806 &errors_ptr, &errors_len)))
19807 {
19808 if (err != ErrorCCompileErrors) {
19809 ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));
19810 return ira->codegen->invalid_inst_gen;
19811 }
19812
19813 ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed"));
19814 if (!ira->codegen->stage1.link_libc) {
19815 add_error_note(ira->codegen, parent_err_msg, node,
19816 buf_sprintf("libc headers not available; compilation does not link against libc"));
19817 }
19818 for (size_t i = 0; i < errors_len; i += 1) {
19819 Stage2ErrorMsg *clang_err = &errors_ptr[i];
19820 // Clang can emit "too many errors, stopping now", in which case
19821 // `source` and `filename_ptr` are null
19822 if (clang_err->source && clang_err->filename_ptr) {
19823 ErrorMsg *err_msg = err_msg_create_with_offset(
19824 clang_err->filename_ptr ?
19825 buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) :
19826 buf_alloc(),
19827 clang_err->offset, clang_err->source,
19828 buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len));
19829 err_msg_add_note(parent_err_msg, err_msg);
19830 }
19831 }
19832
19833 return ira->codegen->invalid_inst_gen;
19834 }
19835 Buf *out_zig_path = buf_create_from_mem(out_zig_path_ptr, out_zig_path_len);
19836
19837 Buf *import_code = buf_alloc();
19838 if ((err = file_fetch(ira->codegen, out_zig_path, import_code))) {
19839 ir_add_error_node(ira, node,
19840 buf_sprintf("unable to open '%s': %s", buf_ptr(out_zig_path), err_str(err)));
19841 return ira->codegen->invalid_inst_gen;
19842 }
19843 ZigType *child_import = add_source_file(ira->codegen, cimport_pkg, out_zig_path,
19844 import_code, SourceKindCImport);
19845 return ir_const_type(ira, instruction->base.scope, instruction->base.source_node, child_import);
19846}
19847
19848static Stage1AirInst *ir_analyze_instruction_c_include(IrAnalyze *ira, Stage1ZirInstCInclude *instruction) {
19849 Stage1AirInst *name_value = instruction->name->child;
19850 if (type_is_invalid(name_value->value->type))
19851 return ira->codegen->invalid_inst_gen;
19852
19853 Buf *include_name = ir_resolve_str(ira, name_value);
19854 if (!include_name)
19855 return ira->codegen->invalid_inst_gen;
19856
19857 Buf *c_import_buf = ira->new_irb.exec->c_import_buf;
19858 // We check for this error in pass1
19859 assert(c_import_buf);
19860
19861 buf_appendf(c_import_buf, "#include <%s>\n", buf_ptr(include_name));
19862
19863 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
19864}
19865
19866static Stage1AirInst *ir_analyze_instruction_c_define(IrAnalyze *ira, Stage1ZirInstCDefine *instruction) {
19867 Stage1AirInst *name = instruction->name->child;
19868 if (type_is_invalid(name->value->type))
19869 return ira->codegen->invalid_inst_gen;
19870
19871 Buf *define_name = ir_resolve_str(ira, name);
19872 if (!define_name)
19873 return ira->codegen->invalid_inst_gen;
19874
19875 Stage1AirInst *value = instruction->value->child;
19876 if (type_is_invalid(value->value->type))
19877 return ira->codegen->invalid_inst_gen;
19878
19879 Buf *define_value = nullptr;
19880 // The second parameter is either a string or void (equivalent to "")
19881 if (value->value->type->id != ZigTypeIdVoid) {
19882 define_value = ir_resolve_str(ira, value);
19883 if (!define_value)
19884 return ira->codegen->invalid_inst_gen;
19885 }
19886
19887 Buf *c_import_buf = ira->new_irb.exec->c_import_buf;
19888 // We check for this error in pass1
19889 assert(c_import_buf);
19890
19891 buf_appendf(c_import_buf, "#define %s %s\n", buf_ptr(define_name),
19892 define_value ? buf_ptr(define_value) : "");
19893
19894 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
19895}
19896
19897static Stage1AirInst *ir_analyze_instruction_c_undef(IrAnalyze *ira, Stage1ZirInstCUndef *instruction) {
19898 Stage1AirInst *name = instruction->name->child;
19899 if (type_is_invalid(name->value->type))
19900 return ira->codegen->invalid_inst_gen;
19901
19902 Buf *undef_name = ir_resolve_str(ira, name);
19903 if (!undef_name)
19904 return ira->codegen->invalid_inst_gen;
19905
19906 Buf *c_import_buf = ira->new_irb.exec->c_import_buf;
19907 // We check for this error in pass1
19908 assert(c_import_buf);
19909
19910 buf_appendf(c_import_buf, "#undef %s\n", buf_ptr(undef_name));
19911
19912 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
19913}
19914
19915static Stage1AirInst *ir_analyze_instruction_embed_file(IrAnalyze *ira, Stage1ZirInstEmbedFile *instruction) {
19916 Stage1AirInst *name = instruction->name->child;
19917 if (type_is_invalid(name->value->type))
19918 return ira->codegen->invalid_inst_gen;
19919
19920 Buf *rel_file_path = ir_resolve_str(ira, name);
19921 if (!rel_file_path)
19922 return ira->codegen->invalid_inst_gen;
19923
19924 ZigType *import = get_scope_import(instruction->base.scope);
19925 // figure out absolute path to resource
19926 Buf source_dir_path = BUF_INIT;
19927 os_path_dirname(import->data.structure.root_struct->path, &source_dir_path);
19928
19929 Buf *resolve_paths[] = {
19930 &source_dir_path,
19931 rel_file_path,
19932 };
19933 Buf *file_path = buf_alloc();
19934 *file_path = os_path_resolve(resolve_paths, 2);
19935
19936 // load from file system into const expr
19937 Buf *file_contents = buf_alloc();
19938 Error err;
19939 if ((err = file_fetch(ira->codegen, file_path, file_contents))) {
19940 if (err == ErrorFileNotFound) {
19941 ir_add_error_node(ira, instruction->name->source_node,
19942 buf_sprintf("unable to find '%s'", buf_ptr(file_path)));
19943 return ira->codegen->invalid_inst_gen;
19944 } else {
19945 ir_add_error_node(ira, instruction->name->source_node,
19946 buf_sprintf("unable to open '%s': %s", buf_ptr(file_path), err_str(err)));
19947 return ira->codegen->invalid_inst_gen;
19948 }
19949 }
19950
19951 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, nullptr);
19952 init_const_str_lit(ira->codegen, result->value, file_contents, true);
19953 return result;
19954}
19955
19956static Stage1AirInst *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, Stage1ZirInstCmpxchg *instruction) {
19957 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);
19958 if (type_is_invalid(operand_type))
19959 return ira->codegen->invalid_inst_gen;
19960
19961 if (operand_type->id == ZigTypeIdFloat) {
19962 ir_add_error(ira, instruction->type_value->child,
19963 buf_sprintf("expected bool, integer, enum or pointer type, found '%s'", buf_ptr(&operand_type->name)));
19964 return ira->codegen->invalid_inst_gen;
19965 }
19966
19967 Stage1AirInst *ptr = instruction->ptr->child;
19968 if (type_is_invalid(ptr->value->type))
19969 return ira->codegen->invalid_inst_gen;
19970
19971 // TODO let this be volatile
19972 ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, false);
19973 Stage1AirInst *casted_ptr = ir_implicit_cast2(ira, instruction->ptr->scope,
19974 instruction->ptr->source_node, ptr, ptr_type);
19975 if (type_is_invalid(casted_ptr->value->type))
19976 return ira->codegen->invalid_inst_gen;
19977
19978 Stage1AirInst *cmp_value = instruction->cmp_value->child;
19979 if (type_is_invalid(cmp_value->value->type))
19980 return ira->codegen->invalid_inst_gen;
19981
19982 Stage1AirInst *new_value = instruction->new_value->child;
19983 if (type_is_invalid(new_value->value->type))
19984 return ira->codegen->invalid_inst_gen;
19985
19986 Stage1AirInst *success_order_value = instruction->success_order_value->child;
19987 if (type_is_invalid(success_order_value->value->type))
19988 return ira->codegen->invalid_inst_gen;
19989
19990 AtomicOrder success_order;
19991 if (!ir_resolve_atomic_order(ira, success_order_value, &success_order))
19992 return ira->codegen->invalid_inst_gen;
19993
19994 Stage1AirInst *failure_order_value = instruction->failure_order_value->child;
19995 if (type_is_invalid(failure_order_value->value->type))
19996 return ira->codegen->invalid_inst_gen;
19997
19998 AtomicOrder failure_order;
19999 if (!ir_resolve_atomic_order(ira, failure_order_value, &failure_order))
20000 return ira->codegen->invalid_inst_gen;
20001
20002 Stage1AirInst *casted_cmp_value = ir_implicit_cast2(ira, instruction->cmp_value->scope,
20003 instruction->cmp_value->source_node, cmp_value, operand_type);
20004 if (type_is_invalid(casted_cmp_value->value->type))
20005 return ira->codegen->invalid_inst_gen;
20006
20007 Stage1AirInst *casted_new_value = ir_implicit_cast2(ira, instruction->new_value->scope,
20008 instruction->new_value->source_node, new_value, operand_type);
20009 if (type_is_invalid(casted_new_value->value->type))
20010 return ira->codegen->invalid_inst_gen;
20011
20012 if (success_order < AtomicOrderMonotonic) {
20013 ir_add_error(ira, success_order_value,
20014 buf_sprintf("success atomic ordering must be Monotonic or stricter"));
20015 return ira->codegen->invalid_inst_gen;
20016 }
20017 if (failure_order < AtomicOrderMonotonic) {
20018 ir_add_error(ira, failure_order_value,
20019 buf_sprintf("failure atomic ordering must be Monotonic or stricter"));
20020 return ira->codegen->invalid_inst_gen;
20021 }
20022 if (failure_order > success_order) {
20023 ir_add_error(ira, failure_order_value,
20024 buf_sprintf("failure atomic ordering must be no stricter than success"));
20025 return ira->codegen->invalid_inst_gen;
20026 }
20027 if (failure_order == AtomicOrderRelease || failure_order == AtomicOrderAcqRel) {
20028 ir_add_error(ira, failure_order_value,
20029 buf_sprintf("failure atomic ordering must not be Release or AcqRel"));
20030 return ira->codegen->invalid_inst_gen;
20031 }
20032
20033 ZigType *result_type = get_optional_type(ira->codegen, operand_type);
20034
20035 // special case zero bit types
20036 switch (type_has_one_possible_value(ira->codegen, operand_type)) {
20037 case OnePossibleValueInvalid:
20038 return ira->codegen->invalid_inst_gen;
20039 case OnePossibleValueYes: {
20040 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, result_type);
20041 set_optional_value_to_null(result->value);
20042 return result;
20043 }
20044 case OnePossibleValueNo:
20045 break;
20046 }
20047
20048 if (instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar &&
20049 instr_is_comptime(casted_cmp_value) && instr_is_comptime(casted_new_value)) {
20050 ZigValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad);
20051 if (ptr_val == nullptr)
20052 return ira->codegen->invalid_inst_gen;
20053
20054 ZigValue *stored_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
20055 if (stored_val == nullptr)
20056 return ira->codegen->invalid_inst_gen;
20057
20058 ZigValue *expected_val = ir_resolve_const(ira, casted_cmp_value, UndefBad);
20059 if (expected_val == nullptr)
20060 return ira->codegen->invalid_inst_gen;
20061
20062 ZigValue *new_val = ir_resolve_const(ira, casted_new_value, UndefBad);
20063 if (new_val == nullptr)
20064 return ira->codegen->invalid_inst_gen;
20065
20066 bool eql = const_values_equal(ira->codegen, stored_val, expected_val);
20067 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, result_type);
20068 if (eql) {
20069 copy_const_val(ira->codegen, stored_val, new_val);
20070 set_optional_value_to_null(result->value);
20071 } else {
20072 set_optional_payload(result->value, stored_val);
20073 }
20074 return result;
20075 }
20076
20077 Stage1AirInst *result_loc;
20078 if (handle_is_ptr(ira->codegen, result_type)) {
20079 result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
20080 result_type, nullptr, true, true);
20081 if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
20082 return result_loc;
20083 }
20084 } else {
20085 result_loc = nullptr;
20086 }
20087
20088 return ir_build_cmpxchg_gen(ira, instruction->base.scope, instruction->base.source_node, result_type,
20089 casted_ptr, casted_cmp_value, casted_new_value,
20090 success_order, failure_order, instruction->is_weak, result_loc);
20091}
20092
20093static ErrorMsg *ir_eval_reduce(IrAnalyze *ira, Scope *scope, AstNode *source_node, ReduceOp op, ZigValue *value, ZigValue *out_value) {
20094 assert(value->type->id == ZigTypeIdVector);
20095 ZigType *scalar_type = value->type->data.vector.elem_type;
20096 const size_t len = value->type->data.vector.len;
20097 assert(len > 0);
20098
20099 out_value->type = scalar_type;
20100 out_value->special = ConstValSpecialStatic;
20101
20102 if (scalar_type->id == ZigTypeIdBool) {
20103 ZigValue *first_elem_val = &value->data.x_array.data.s_none.elements[0];
20104
20105 bool result = first_elem_val->data.x_bool;
20106 for (size_t i = 1; i < len; i++) {
20107 ZigValue *elem_val = &value->data.x_array.data.s_none.elements[i];
20108
20109 switch (op) {
20110 case ReduceOp_and:
20111 result = result && elem_val->data.x_bool;
20112 if (!result) break; // Short circuit
20113 break;
20114 case ReduceOp_or:
20115 result = result || elem_val->data.x_bool;
20116 if (result) break; // Short circuit
20117 break;
20118 case ReduceOp_xor:
20119 result = result != elem_val->data.x_bool;
20120 break;
20121 default:
20122 zig_unreachable();
20123 }
20124 }
20125
20126 out_value->data.x_bool = result;
20127 return nullptr;
20128 }
20129
20130 // Evaluate and/or/xor.
20131 if (op == ReduceOp_and || op == ReduceOp_or || op == ReduceOp_xor) {
20132 ZigValue *first_elem_val = &value->data.x_array.data.s_none.elements[0];
20133
20134 copy_const_val(ira->codegen, out_value, first_elem_val);
20135
20136 for (size_t i = 1; i < len; i++) {
20137 ZigValue *elem_val = &value->data.x_array.data.s_none.elements[i];
20138
20139 IrBinOp bin_op;
20140 switch (op) {
20141 case ReduceOp_and: bin_op = IrBinOpBinAnd; break;
20142 case ReduceOp_or: bin_op = IrBinOpBinOr; break;
20143 case ReduceOp_xor: bin_op = IrBinOpBinXor; break;
20144 default: zig_unreachable();
20145 }
20146
20147 ErrorMsg *msg = ir_eval_math_op_scalar(ira, scope, source_node, scalar_type,
20148 out_value, bin_op, elem_val, out_value);
20149 if (msg != nullptr)
20150 return msg;
20151 }
20152
20153 return nullptr;
20154 }
20155
20156 // Evaluate add/sub.
20157 // Perform the reduction sequentially, starting from the neutral value.
20158 if (op == ReduceOp_add || op == ReduceOp_mul) {
20159 if (scalar_type->id == ZigTypeIdInt) {
20160 if (op == ReduceOp_add) {
20161 bigint_init_unsigned(&out_value->data.x_bigint, 0);
20162 } else {
20163 bigint_init_unsigned(&out_value->data.x_bigint, 1);
20164 }
20165 } else {
20166 if (op == ReduceOp_add) {
20167 float_init_f64(out_value, -0.0);
20168 } else {
20169 float_init_f64(out_value, 1.0);
20170 }
20171 }
20172
20173 for (size_t i = 0; i < len; i++) {
20174 ZigValue *elem_val = &value->data.x_array.data.s_none.elements[i];
20175
20176 IrBinOp bin_op;
20177 switch (op) {
20178 case ReduceOp_add: bin_op = IrBinOpAdd; break;
20179 case ReduceOp_mul: bin_op = IrBinOpMult; break;
20180 default: zig_unreachable();
20181 }
20182
20183 ErrorMsg *msg = ir_eval_math_op_scalar(ira, scope, source_node, scalar_type,
20184 out_value, bin_op, elem_val, out_value);
20185 if (msg != nullptr)
20186 return msg;
20187 }
20188
20189 return nullptr;
20190 }
20191
20192 // Evaluate min/max.
20193 ZigValue *candidate_elem_val = &value->data.x_array.data.s_none.elements[0];
20194
20195 ZigValue *dummy_cmp_value = ira->codegen->pass1_arena->create<ZigValue>();
20196 for (size_t i = 1; i < len; i++) {
20197 ZigValue *elem_val = &value->data.x_array.data.s_none.elements[i];
20198
20199 IrBinOp bin_op;
20200 switch (op) {
20201 case ReduceOp_min: bin_op = IrBinOpCmpLessThan; break;
20202 case ReduceOp_max: bin_op = IrBinOpCmpGreaterThan; break;
20203 default: zig_unreachable();
20204 }
20205
20206 ErrorMsg *msg = ir_eval_bin_op_cmp_scalar(ira, scope, source_node,
20207 elem_val, bin_op, candidate_elem_val, dummy_cmp_value);
20208 if (msg != nullptr)
20209 return msg;
20210
20211 if (dummy_cmp_value->data.x_bool)
20212 candidate_elem_val = elem_val;
20213 }
20214
20215 ira->codegen->pass1_arena->destroy(dummy_cmp_value);
20216 copy_const_val(ira->codegen, out_value, candidate_elem_val);
20217
20218 return nullptr;
20219}
20220
20221static Stage1AirInst *ir_analyze_instruction_reduce(IrAnalyze *ira, Stage1ZirInstReduce *instruction) {
20222 Stage1AirInst *op_inst = instruction->op->child;
20223 if (type_is_invalid(op_inst->value->type))
20224 return ira->codegen->invalid_inst_gen;
20225
20226 Stage1AirInst *value_inst = instruction->value->child;
20227 if (type_is_invalid(value_inst->value->type))
20228 return ira->codegen->invalid_inst_gen;
20229
20230 ZigType *value_type = value_inst->value->type;
20231 if (value_type->id != ZigTypeIdVector) {
20232 ir_add_error(ira, value_inst,
20233 buf_sprintf("expected vector type, found '%s'",
20234 buf_ptr(&value_type->name)));
20235 return ira->codegen->invalid_inst_gen;
20236 }
20237
20238 ReduceOp op;
20239 if (!ir_resolve_reduce_op(ira, op_inst, &op))
20240 return ira->codegen->invalid_inst_gen;
20241
20242 ZigType *elem_type = value_type->data.vector.elem_type;
20243 switch (elem_type->id) {
20244 case ZigTypeIdInt:
20245 break;
20246 case ZigTypeIdBool:
20247 if (op > ReduceOp_xor) {
20248 ir_add_error(ira, op_inst,
20249 buf_sprintf("invalid operation for '%s' type",
20250 buf_ptr(&elem_type->name)));
20251 return ira->codegen->invalid_inst_gen;
20252 } break;
20253 case ZigTypeIdFloat:
20254 if (op < ReduceOp_min) {
20255 ir_add_error(ira, op_inst,
20256 buf_sprintf("invalid operation for '%s' type",
20257 buf_ptr(&elem_type->name)));
20258 return ira->codegen->invalid_inst_gen;
20259 } break;
20260 default:
20261 // Vectors cannot have child types other than those listed above
20262 zig_unreachable();
20263 }
20264
20265 // special case zero bit types
20266 switch (type_has_one_possible_value(ira->codegen, elem_type)) {
20267 case OnePossibleValueInvalid:
20268 return ira->codegen->invalid_inst_gen;
20269 case OnePossibleValueYes:
20270 return ir_const_move(ira, instruction->base.scope, instruction->base.source_node,
20271 get_the_one_possible_value(ira->codegen, elem_type));
20272 case OnePossibleValueNo:
20273 break;
20274 }
20275
20276 if (instr_is_comptime(value_inst)) {
20277 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, elem_type);
20278 if (ir_eval_reduce(ira, instruction->base.scope, instruction->base.source_node, op, value_inst->value, result->value))
20279 return ira->codegen->invalid_inst_gen;
20280 return result;
20281 }
20282
20283 return ir_build_reduce_gen(ira, instruction->base.scope, instruction->base.source_node, op, value_inst, elem_type);
20284}
20285
20286static Stage1AirInst *ir_analyze_instruction_fence(IrAnalyze *ira, Stage1ZirInstFence *instruction) {
20287 Stage1AirInst *order_inst = instruction->order->child;
20288 if (type_is_invalid(order_inst->value->type))
20289 return ira->codegen->invalid_inst_gen;
20290
20291 AtomicOrder order;
20292 if (!ir_resolve_atomic_order(ira, order_inst, &order))
20293 return ira->codegen->invalid_inst_gen;
20294
20295 if (order < AtomicOrderAcquire) {
20296 ir_add_error(ira, order_inst,
20297 buf_sprintf("atomic ordering must be Acquire or stricter"));
20298 return ira->codegen->invalid_inst_gen;
20299 }
20300
20301 return ir_build_fence_gen(ira, instruction->base.scope, instruction->base.source_node, order);
20302}
20303
20304static Stage1AirInst *ir_analyze_instruction_truncate(IrAnalyze *ira, Stage1ZirInstTruncate *instruction) {
20305 Stage1AirInst *dest_type_value = instruction->dest_type->child;
20306 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20307 if (type_is_invalid(dest_type))
20308 return ira->codegen->invalid_inst_gen;
20309
20310 Stage1AirInst *operand = instruction->target->child;
20311 if (type_is_invalid(operand->value->type))
20312 return ira->codegen->invalid_inst_gen;
20313
20314 return ir_analyze_truncate(ira, instruction->base.scope, instruction->base.source_node,
20315 dest_type, instruction->dest_type->source_node,
20316 operand, instruction->target->source_node);
20317}
20318
20319static Stage1AirInst *ir_analyze_int_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node,
20320 ZigType *dest_type, AstNode *dest_type_src_node,
20321 Stage1AirInst *target, AstNode *target_src_node)
20322{
20323 ZigType *scalar_dest_type = (dest_type->id == ZigTypeIdVector) ?
20324 dest_type->data.vector.elem_type : dest_type;
20325
20326 if (scalar_dest_type->id != ZigTypeIdInt && scalar_dest_type->id != ZigTypeIdComptimeInt) {
20327 ir_add_error_node(ira, dest_type_src_node,
20328 buf_sprintf("expected integer type, found '%s'", buf_ptr(&scalar_dest_type->name)));
20329 return ira->codegen->invalid_inst_gen;
20330 }
20331
20332 ZigType *scalar_target_type = (target->value->type->id == ZigTypeIdVector) ?
20333 target->value->type->data.vector.elem_type : target->value->type;
20334
20335 if (scalar_target_type->id != ZigTypeIdInt && scalar_target_type->id != ZigTypeIdComptimeInt) {
20336 ir_add_error_node(ira, target_src_node, buf_sprintf("expected integer type, found '%s'",
20337 buf_ptr(&scalar_target_type->name)));
20338 return ira->codegen->invalid_inst_gen;
20339 }
20340
20341 if (scalar_dest_type->id == ZigTypeIdComptimeInt) {
20342 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
20343 if (val == nullptr)
20344 return ira->codegen->invalid_inst_gen;
20345
20346 return ir_implicit_cast2(ira, scope, target_src_node, target, dest_type);
20347 }
20348
20349 return ir_analyze_widen_or_shorten(ira, scope, source_node, target, dest_type);
20350}
20351
20352static Stage1AirInst *ir_analyze_instruction_int_cast(IrAnalyze *ira, Stage1ZirInstIntCast *instruction) {
20353 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
20354 if (type_is_invalid(dest_type))
20355 return ira->codegen->invalid_inst_gen;
20356
20357 Stage1AirInst *target = instruction->target->child;
20358 if (type_is_invalid(target->value->type))
20359 return ira->codegen->invalid_inst_gen;
20360
20361 return ir_analyze_int_cast(ira, instruction->base.scope, instruction->base.source_node,
20362 dest_type, instruction->dest_type->source_node,
20363 target, instruction->target->source_node);
20364}
20365
20366static Stage1AirInst *ir_analyze_instruction_float_cast(IrAnalyze *ira, Stage1ZirInstFloatCast *instruction) {
20367 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
20368 if (type_is_invalid(dest_type))
20369 return ira->codegen->invalid_inst_gen;
20370
20371 if (dest_type->id != ZigTypeIdFloat && dest_type->id != ZigTypeIdComptimeFloat) {
20372 ir_add_error_node(ira, instruction->dest_type->source_node,
20373 buf_sprintf("expected float type, found '%s'", buf_ptr(&dest_type->name)));
20374 return ira->codegen->invalid_inst_gen;
20375 }
20376
20377 Stage1AirInst *target = instruction->target->child;
20378 if (type_is_invalid(target->value->type))
20379 return ira->codegen->invalid_inst_gen;
20380
20381 if (target->value->type->id == ZigTypeIdComptimeInt ||
20382 target->value->type->id == ZigTypeIdComptimeFloat)
20383 {
20384 if (ir_num_lit_fits_in_other_type(ira, target, dest_type, true)) {
20385 CastOp op;
20386 if (target->value->type->id == ZigTypeIdComptimeInt) {
20387 op = CastOpIntToFloat;
20388 } else {
20389 op = CastOpNumLitToConcrete;
20390 }
20391 return ir_resolve_cast(ira, instruction->base.scope, instruction->base.source_node, target, dest_type, op);
20392 } else {
20393 return ira->codegen->invalid_inst_gen;
20394 }
20395 }
20396
20397 if (target->value->type->id != ZigTypeIdFloat) {
20398 ir_add_error_node(ira, instruction->target->source_node, buf_sprintf("expected float type, found '%s'",
20399 buf_ptr(&target->value->type->name)));
20400 return ira->codegen->invalid_inst_gen;
20401 }
20402
20403 if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeFloat) {
20404 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
20405 if (val == nullptr)
20406 return ira->codegen->invalid_inst_gen;
20407
20408 // XXX: This will trigger an assertion failure if dest_type is comptime_float
20409 return ir_analyze_widen_or_shorten(ira, instruction->target->scope,
20410 instruction->target->source_node, target, dest_type);
20411 }
20412
20413 return ir_analyze_widen_or_shorten(ira, instruction->base.scope, instruction->base.source_node, target, dest_type);
20414}
20415
20416static Stage1AirInst *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, Stage1ZirInstErrSetCast *instruction) {
20417 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
20418 if (type_is_invalid(dest_type))
20419 return ira->codegen->invalid_inst_gen;
20420
20421 if (dest_type->id != ZigTypeIdErrorSet) {
20422 ir_add_error_node(ira, instruction->dest_type->source_node,
20423 buf_sprintf("expected error set type, found '%s'", buf_ptr(&dest_type->name)));
20424 return ira->codegen->invalid_inst_gen;
20425 }
20426
20427 Stage1AirInst *target = instruction->target->child;
20428 if (type_is_invalid(target->value->type))
20429 return ira->codegen->invalid_inst_gen;
20430
20431 if (target->value->type->id != ZigTypeIdErrorSet) {
20432 ir_add_error_node(ira, instruction->target->source_node,
20433 buf_sprintf("expected error set type, found '%s'", buf_ptr(&target->value->type->name)));
20434 return ira->codegen->invalid_inst_gen;
20435 }
20436
20437 return ir_analyze_err_set_cast(ira, instruction->base.scope, instruction->base.source_node, target, dest_type);
20438}
20439
20440static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
20441 Error err;
20442
20443 ZigType *ptr_type;
20444 if (is_slice(ty)) {
20445 TypeStructField *ptr_field = ty->data.structure.fields[slice_ptr_index];
20446 ptr_type = resolve_struct_field_type(ira->codegen, ptr_field);
20447 } else {
20448 ptr_type = get_src_ptr_type(ty);
20449 }
20450 assert(ptr_type != nullptr);
20451 if (ptr_type->id == ZigTypeIdPointer) {
20452 if ((err = type_resolve(ira->codegen, ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
20453 return err;
20454 } else if (is_slice(ptr_type)) {
20455 TypeStructField *ptr_field = ptr_type->data.structure.fields[slice_ptr_index];
20456 ZigType *slice_ptr_type = resolve_struct_field_type(ira->codegen, ptr_field);
20457 if ((err = type_resolve(ira->codegen, slice_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
20458 return err;
20459 }
20460
20461 *result_align = get_ptr_align(ira->codegen, ty);
20462 return ErrorNone;
20463}
20464
20465static Stage1AirInst *ir_analyze_instruction_int_to_float(IrAnalyze *ira, Stage1ZirInstIntToFloat *instruction) {
20466 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
20467 if (type_is_invalid(dest_type))
20468 return ira->codegen->invalid_inst_gen;
20469
20470 if (dest_type->id != ZigTypeIdFloat && dest_type->id != ZigTypeIdComptimeFloat) {
20471 ir_add_error_node(ira, instruction->dest_type->source_node,
20472 buf_sprintf("expected float type, found '%s'", buf_ptr(&dest_type->name)));
20473 return ira->codegen->invalid_inst_gen;
20474 }
20475
20476 Stage1AirInst *target = instruction->target->child;
20477 if (type_is_invalid(target->value->type))
20478 return ira->codegen->invalid_inst_gen;
20479
20480 if (target->value->type->id != ZigTypeIdInt && target->value->type->id != ZigTypeIdComptimeInt) {
20481 ir_add_error_node(ira, instruction->target->source_node,
20482 buf_sprintf("expected int type, found '%s'", buf_ptr(&target->value->type->name)));
20483 return ira->codegen->invalid_inst_gen;
20484 }
20485
20486 return ir_resolve_cast(ira, instruction->base.scope, instruction->base.source_node, target, dest_type, CastOpIntToFloat);
20487}
20488
20489static Stage1AirInst *ir_analyze_instruction_float_to_int(IrAnalyze *ira, Stage1ZirInstFloatToInt *instruction) {
20490 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
20491 if (type_is_invalid(dest_type))
20492 return ira->codegen->invalid_inst_gen;
20493
20494 if (dest_type->id != ZigTypeIdInt && dest_type->id != ZigTypeIdComptimeInt) {
20495 ir_add_error_node(ira, instruction->dest_type->source_node,
20496 buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));
20497 return ira->codegen->invalid_inst_gen;
20498 }
20499
20500 Stage1AirInst *target = instruction->target->child;
20501 if (type_is_invalid(target->value->type))
20502 return ira->codegen->invalid_inst_gen;
20503
20504 if (target->value->type->id == ZigTypeIdComptimeInt) {
20505 return ir_implicit_cast(ira, target, dest_type);
20506 }
20507
20508 if (target->value->type->id != ZigTypeIdFloat && target->value->type->id != ZigTypeIdComptimeFloat) {
20509 ir_add_error_node(ira, target->source_node, buf_sprintf("expected float type, found '%s'",
20510 buf_ptr(&target->value->type->name)));
20511 return ira->codegen->invalid_inst_gen;
20512 }
20513
20514 return ir_resolve_cast(ira, instruction->base.scope, instruction->base.source_node, target, dest_type, CastOpFloatToInt);
20515}
20516
20517static Stage1AirInst *ir_analyze_instruction_err_to_int(IrAnalyze *ira, Stage1ZirInstErrToInt *instruction) {
20518 Stage1AirInst *target = instruction->target->child;
20519 if (type_is_invalid(target->value->type))
20520 return ira->codegen->invalid_inst_gen;
20521
20522 Stage1AirInst *casted_target;
20523 if (target->value->type->id == ZigTypeIdErrorSet) {
20524 casted_target = target;
20525 } else {
20526 casted_target = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_global_error_set);
20527 if (type_is_invalid(casted_target->value->type))
20528 return ira->codegen->invalid_inst_gen;
20529 }
20530
20531 return ir_analyze_err_to_int(ira, instruction->base.scope, instruction->base.source_node, casted_target, ira->codegen->err_tag_type);
20532}
20533
20534static Stage1AirInst *ir_analyze_instruction_int_to_err(IrAnalyze *ira, Stage1ZirInstIntToErr *instruction) {
20535 Stage1AirInst *target = instruction->target->child;
20536 if (type_is_invalid(target->value->type))
20537 return ira->codegen->invalid_inst_gen;
20538
20539 Stage1AirInst *casted_target = ir_implicit_cast(ira, target, ira->codegen->err_tag_type);
20540 if (type_is_invalid(casted_target->value->type))
20541 return ira->codegen->invalid_inst_gen;
20542
20543 return ir_analyze_int_to_err(ira, instruction->base.scope, instruction->base.source_node, casted_target, ira->codegen->builtin_types.entry_global_error_set);
20544}
20545
20546static Stage1AirInst *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, Stage1ZirInstBoolToInt *instruction) {
20547 Stage1AirInst *target = instruction->target->child;
20548 if (type_is_invalid(target->value->type))
20549 return ira->codegen->invalid_inst_gen;
20550
20551 if (target->value->type->id != ZigTypeIdBool) {
20552 ir_add_error_node(ira, instruction->target->source_node,
20553 buf_sprintf("expected bool, found '%s'", buf_ptr(&target->value->type->name)));
20554 return ira->codegen->invalid_inst_gen;
20555 }
20556
20557 if (instr_is_comptime(target)) {
20558 bool is_true;
20559 if (!ir_resolve_bool(ira, target, &is_true))
20560 return ira->codegen->invalid_inst_gen;
20561
20562 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, is_true ? 1 : 0);
20563 }
20564
20565 ZigType *u1_type = get_int_type(ira->codegen, false, 1);
20566 return ir_resolve_cast(ira, instruction->base.scope, instruction->base.source_node, target, u1_type, CastOpBoolToInt);
20567}
20568
20569static Stage1AirInst *ir_analyze_instruction_vector_type(IrAnalyze *ira, Stage1ZirInstVectorType *instruction) {
20570 uint64_t len;
20571 if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len))
20572 return ira->codegen->invalid_inst_gen;
20573
20574 ZigType *elem_type = ir_resolve_vector_elem_type(ira, instruction->elem_type->child);
20575 if (type_is_invalid(elem_type))
20576 return ira->codegen->invalid_inst_gen;
20577
20578 ZigType *vector_type = get_vector_type(ira->codegen, len, elem_type);
20579
20580 return ir_const_type(ira, instruction->base.scope, instruction->base.source_node, vector_type);
20581}
20582
20583static Stage1AirInst *ir_analyze_shuffle_vector(IrAnalyze *ira, Scope *scope, AstNode *source_node,
20584 ZigType *scalar_type, Stage1AirInst *a, Stage1AirInst *b, Stage1AirInst *mask)
20585{
20586 Error err;
20587 src_assert(source_node && scalar_type && a && b && mask, source_node);
20588
20589 if ((err = ir_validate_vector_elem_type(ira, source_node, scalar_type)))
20590 return ira->codegen->invalid_inst_gen;
20591
20592 uint32_t len_mask;
20593 if (mask->value->type->id == ZigTypeIdVector) {
20594 len_mask = mask->value->type->data.vector.len;
20595 } else if (mask->value->type->id == ZigTypeIdArray) {
20596 len_mask = mask->value->type->data.array.len;
20597 } else {
20598 ir_add_error(ira, mask,
20599 buf_sprintf("expected vector or array, found '%s'",
20600 buf_ptr(&mask->value->type->name)));
20601 return ira->codegen->invalid_inst_gen;
20602 }
20603 mask = ir_implicit_cast(ira, mask, get_vector_type(ira->codegen, len_mask,
20604 ira->codegen->builtin_types.entry_i32));
20605 if (type_is_invalid(mask->value->type))
20606 return ira->codegen->invalid_inst_gen;
20607
20608 uint32_t len_a;
20609 if (a->value->type->id == ZigTypeIdVector) {
20610 len_a = a->value->type->data.vector.len;
20611 } else if (a->value->type->id == ZigTypeIdArray) {
20612 len_a = a->value->type->data.array.len;
20613 } else if (a->value->type->id == ZigTypeIdUndefined) {
20614 len_a = UINT32_MAX;
20615 } else {
20616 ir_add_error(ira, a,
20617 buf_sprintf("expected vector or array with element type '%s', found '%s'",
20618 buf_ptr(&scalar_type->name),
20619 buf_ptr(&a->value->type->name)));
20620 return ira->codegen->invalid_inst_gen;
20621 }
20622
20623 uint32_t len_b;
20624 if (b->value->type->id == ZigTypeIdVector) {
20625 len_b = b->value->type->data.vector.len;
20626 } else if (b->value->type->id == ZigTypeIdArray) {
20627 len_b = b->value->type->data.array.len;
20628 } else if (b->value->type->id == ZigTypeIdUndefined) {
20629 len_b = UINT32_MAX;
20630 } else {
20631 ir_add_error(ira, b,
20632 buf_sprintf("expected vector or array with element type '%s', found '%s'",
20633 buf_ptr(&scalar_type->name),
20634 buf_ptr(&b->value->type->name)));
20635 return ira->codegen->invalid_inst_gen;
20636 }
20637
20638 if (len_a == UINT32_MAX && len_b == UINT32_MAX) {
20639 return ir_const_undef(ira, a->scope, a->source_node, get_vector_type(ira->codegen, len_mask, scalar_type));
20640 }
20641
20642 if (len_a == UINT32_MAX) {
20643 len_a = len_b;
20644 a = ir_const_undef(ira, a->scope, a->source_node, get_vector_type(ira->codegen, len_a, scalar_type));
20645 } else {
20646 a = ir_implicit_cast(ira, a, get_vector_type(ira->codegen, len_a, scalar_type));
20647 if (type_is_invalid(a->value->type))
20648 return ira->codegen->invalid_inst_gen;
20649 }
20650
20651 if (len_b == UINT32_MAX) {
20652 len_b = len_a;
20653 b = ir_const_undef(ira, b->scope, b->source_node, get_vector_type(ira->codegen, len_b, scalar_type));
20654 } else {
20655 b = ir_implicit_cast(ira, b, get_vector_type(ira->codegen, len_b, scalar_type));
20656 if (type_is_invalid(b->value->type))
20657 return ira->codegen->invalid_inst_gen;
20658 }
20659
20660 ZigValue *mask_val = ir_resolve_const(ira, mask, UndefOk);
20661 if (mask_val == nullptr)
20662 return ira->codegen->invalid_inst_gen;
20663
20664 expand_undef_array(ira->codegen, mask_val);
20665
20666 for (uint32_t i = 0; i < len_mask; i += 1) {
20667 ZigValue *mask_elem_val = &mask_val->data.x_array.data.s_none.elements[i];
20668 if (mask_elem_val->special == ConstValSpecialUndef)
20669 continue;
20670 int32_t v_i32 = bigint_as_signed(&mask_elem_val->data.x_bigint);
20671 uint32_t v;
20672 Stage1AirInst *chosen_operand;
20673 if (v_i32 >= 0) {
20674 v = (uint32_t)v_i32;
20675 chosen_operand = a;
20676 } else {
20677 v = (uint32_t)~v_i32;
20678 chosen_operand = b;
20679 }
20680 if (v >= chosen_operand->value->type->data.vector.len) {
20681 ErrorMsg *msg = ir_add_error(ira, mask,
20682 buf_sprintf("mask index '%u' has out-of-bounds selection", i));
20683 add_error_note(ira->codegen, msg, chosen_operand->source_node,
20684 buf_sprintf("selected index '%u' out of bounds of %s", v,
20685 buf_ptr(&chosen_operand->value->type->name)));
20686 if (chosen_operand == a && v < len_a + len_b) {
20687 add_error_note(ira->codegen, msg, b->source_node,
20688 buf_create_from_str("selections from the second vector are specified with negative numbers"));
20689 }
20690 return ira->codegen->invalid_inst_gen;
20691 }
20692 }
20693
20694 ZigType *result_type = get_vector_type(ira->codegen, len_mask, scalar_type);
20695 if (instr_is_comptime(a) && instr_is_comptime(b)) {
20696 ZigValue *a_val = ir_resolve_const(ira, a, UndefOk);
20697 if (a_val == nullptr)
20698 return ira->codegen->invalid_inst_gen;
20699
20700 ZigValue *b_val = ir_resolve_const(ira, b, UndefOk);
20701 if (b_val == nullptr)
20702 return ira->codegen->invalid_inst_gen;
20703
20704 expand_undef_array(ira->codegen, a_val);
20705 expand_undef_array(ira->codegen, b_val);
20706
20707 Stage1AirInst *result = ir_const(ira, scope, source_node, result_type);
20708 result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(len_mask);
20709 for (uint32_t i = 0; i < mask_val->type->data.vector.len; i += 1) {
20710 ZigValue *mask_elem_val = &mask_val->data.x_array.data.s_none.elements[i];
20711 ZigValue *result_elem_val = &result->value->data.x_array.data.s_none.elements[i];
20712 if (mask_elem_val->special == ConstValSpecialUndef) {
20713 result_elem_val->special = ConstValSpecialUndef;
20714 continue;
20715 }
20716 int32_t v = bigint_as_signed(&mask_elem_val->data.x_bigint);
20717 // We've already checked for and emitted compile errors for index out of bounds here.
20718 ZigValue *src_elem_val = (v >= 0) ?
20719 &a->value->data.x_array.data.s_none.elements[v] :
20720 &b->value->data.x_array.data.s_none.elements[~v];
20721 copy_const_val(ira->codegen, result_elem_val, src_elem_val);
20722
20723 src_assert(result_elem_val->special == ConstValSpecialStatic, source_node);
20724 }
20725 result->value->special = ConstValSpecialStatic;
20726 return result;
20727 }
20728
20729 // All static analysis passed, and not comptime.
20730 // For runtime codegen, vectors a and b must be the same length. Here we
20731 // recursively @shuffle the smaller vector to append undefined elements
20732 // to it up to the length of the longer vector. This recursion terminates
20733 // in 1 call because these calls to ir_analyze_shuffle_vector guarantee
20734 // len_a == len_b.
20735 if (len_a != len_b) {
20736 uint32_t len_min = min(len_a, len_b);
20737 uint32_t len_max = max(len_a, len_b);
20738
20739 Stage1AirInst *expand_mask = ir_const(ira, mask->scope, mask->source_node,
20740 get_vector_type(ira->codegen, len_max, ira->codegen->builtin_types.entry_i32));
20741 expand_mask->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(len_max);
20742 uint32_t i = 0;
20743 for (; i < len_min; i += 1)
20744 bigint_init_unsigned(&expand_mask->value->data.x_array.data.s_none.elements[i].data.x_bigint, i);
20745 for (; i < len_max; i += 1)
20746 bigint_init_signed(&expand_mask->value->data.x_array.data.s_none.elements[i].data.x_bigint, -1);
20747
20748 Stage1AirInst *undef = ir_const_undef(ira, scope, source_node,
20749 get_vector_type(ira->codegen, len_min, scalar_type));
20750
20751 if (len_b < len_a) {
20752 b = ir_analyze_shuffle_vector(ira, scope, source_node, scalar_type, b, undef, expand_mask);
20753 } else {
20754 a = ir_analyze_shuffle_vector(ira, scope, source_node, scalar_type, a, undef, expand_mask);
20755 }
20756 }
20757
20758 return ir_build_shuffle_vector_gen(ira, scope, source_node,
20759 result_type, a, b, mask);
20760}
20761
20762static Stage1AirInst *ir_analyze_instruction_shuffle_vector(IrAnalyze *ira, Stage1ZirInstShuffleVector *instruction) {
20763 ZigType *scalar_type = ir_resolve_vector_elem_type(ira, instruction->scalar_type->child);
20764 if (type_is_invalid(scalar_type))
20765 return ira->codegen->invalid_inst_gen;
20766
20767 Stage1AirInst *a = instruction->a->child;
20768 if (type_is_invalid(a->value->type))
20769 return ira->codegen->invalid_inst_gen;
20770
20771 Stage1AirInst *b = instruction->b->child;
20772 if (type_is_invalid(b->value->type))
20773 return ira->codegen->invalid_inst_gen;
20774
20775 Stage1AirInst *mask = instruction->mask->child;
20776 if (type_is_invalid(mask->value->type))
20777 return ira->codegen->invalid_inst_gen;
20778
20779 return ir_analyze_shuffle_vector(ira, instruction->base.scope, instruction->base.source_node, scalar_type, a, b, mask);
20780}
20781
20782static Stage1AirInst *ir_analyze_instruction_select(IrAnalyze *ira, Stage1ZirInstSelect *instruction) {
20783 Error err;
20784
20785 ZigType *scalar_type = ir_resolve_vector_elem_type(ira, instruction->scalar_type->child);
20786 if (type_is_invalid(scalar_type))
20787 return ira->codegen->invalid_inst_gen;
20788
20789 if ((err = ir_validate_vector_elem_type(ira, instruction->base.source_node, scalar_type)))
20790 return ira->codegen->invalid_inst_gen;
20791
20792 Stage1AirInst *pred = instruction->pred->child;
20793 if (type_is_invalid(pred->value->type))
20794 return ira->codegen->invalid_inst_gen;
20795
20796 Stage1AirInst *a = instruction->a->child;
20797 if (type_is_invalid(a->value->type))
20798 return ira->codegen->invalid_inst_gen;
20799
20800 Stage1AirInst *b = instruction->b->child;
20801 if (type_is_invalid(b->value->type))
20802 return ira->codegen->invalid_inst_gen;
20803
20804 if (pred->value->type->id != ZigTypeIdVector) {
20805 ir_add_error(ira, pred,
20806 buf_sprintf("expected vector type, found '%s'",
20807 buf_ptr(&pred->value->type->name)));
20808 return ira->codegen->invalid_inst_gen;
20809 }
20810
20811 uint32_t pred_len = pred->value->type->data.vector.len;
20812 pred = ir_implicit_cast(ira, pred, get_vector_type(ira->codegen, pred_len,
20813 ira->codegen->builtin_types.entry_bool));
20814 if (type_is_invalid(pred->value->type))
20815 return ira->codegen->invalid_inst_gen;
20816
20817 if (a->value->type->id != ZigTypeIdVector) {
20818 ir_add_error(ira, a,
20819 buf_sprintf("expected vector type, found '%s'",
20820 buf_ptr(&a->value->type->name)));
20821 return ira->codegen->invalid_inst_gen;
20822 }
20823
20824 if (b->value->type->id != ZigTypeIdVector) {
20825 ir_add_error(ira, b,
20826 buf_sprintf("expected vector type, found '%s'",
20827 buf_ptr(&b->value->type->name)));
20828 return ira->codegen->invalid_inst_gen;
20829 }
20830
20831 ZigType *result_type = get_vector_type(ira->codegen, pred_len, scalar_type);
20832
20833 a = ir_implicit_cast(ira, a, result_type);
20834 if (type_is_invalid(a->value->type))
20835 return ira->codegen->invalid_inst_gen;
20836
20837 b = ir_implicit_cast(ira, b, result_type);
20838 if (type_is_invalid(a->value->type))
20839 return ira->codegen->invalid_inst_gen;
20840
20841 if (instr_is_comptime(pred) && instr_is_comptime(a) && instr_is_comptime(b)) {
20842 ZigValue *pred_val = ir_resolve_const(ira, pred, UndefBad);
20843 if (pred_val == nullptr)
20844 return ira->codegen->invalid_inst_gen;
20845
20846 ZigValue *a_val = ir_resolve_const(ira, a, UndefBad);
20847 if (a_val == nullptr)
20848 return ira->codegen->invalid_inst_gen;
20849
20850 ZigValue *b_val = ir_resolve_const(ira, b, UndefBad);
20851 if (b_val == nullptr)
20852 return ira->codegen->invalid_inst_gen;
20853
20854 expand_undef_array(ira->codegen, a_val);
20855 expand_undef_array(ira->codegen, b_val);
20856
20857 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, result_type);
20858 result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(pred_len);
20859
20860 for (uint64_t i = 0; i < pred_len; i += 1) {
20861 ZigValue *dst_elem_val = &result->value->data.x_array.data.s_none.elements[i];
20862 ZigValue *pred_elem_val = &pred_val->data.x_array.data.s_none.elements[i];
20863 ZigValue *a_elem_val = &a_val->data.x_array.data.s_none.elements[i];
20864 ZigValue *b_elem_val = &b_val->data.x_array.data.s_none.elements[i];
20865 ZigValue *result_elem_val = pred_elem_val->data.x_bool ? a_elem_val : b_elem_val;
20866 copy_const_val(ira->codegen, dst_elem_val, result_elem_val);
20867 }
20868
20869 result->value->special = ConstValSpecialStatic;
20870 return result;
20871 }
20872
20873 return ir_build_select_gen(ira, instruction->base.scope, instruction->base.source_node, result_type, pred, a, b);
20874}
20875
20876static Stage1AirInst *ir_analyze_instruction_splat(IrAnalyze *ira, Stage1ZirInstSplat *instruction) {
20877 Error err;
20878
20879 Stage1AirInst *len = instruction->len->child;
20880 if (type_is_invalid(len->value->type))
20881 return ira->codegen->invalid_inst_gen;
20882
20883 Stage1AirInst *scalar = instruction->scalar->child;
20884 if (type_is_invalid(scalar->value->type))
20885 return ira->codegen->invalid_inst_gen;
20886
20887 uint64_t len_u64;
20888 if (!ir_resolve_unsigned(ira, len, ira->codegen->builtin_types.entry_u32, &len_u64))
20889 return ira->codegen->invalid_inst_gen;
20890 uint32_t len_int = len_u64;
20891
20892 if ((err = ir_validate_vector_elem_type(ira, scalar->source_node, scalar->value->type)))
20893 return ira->codegen->invalid_inst_gen;
20894
20895 ZigType *return_type = get_vector_type(ira->codegen, len_int, scalar->value->type);
20896
20897 if (instr_is_comptime(scalar)) {
20898 ZigValue *scalar_val = ir_resolve_const(ira, scalar, UndefOk);
20899 if (scalar_val == nullptr)
20900 return ira->codegen->invalid_inst_gen;
20901 if (scalar_val->special == ConstValSpecialUndef)
20902 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, return_type);
20903
20904 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, return_type);
20905 result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(len_int);
20906 for (uint32_t i = 0; i < len_int; i += 1) {
20907 copy_const_val(ira->codegen, &result->value->data.x_array.data.s_none.elements[i], scalar_val);
20908 }
20909 return result;
20910 }
20911
20912 return ir_build_splat_gen(ira, instruction->base.scope, instruction->base.source_node, return_type, scalar);
20913}
20914
20915static Stage1AirInst *ir_analyze_instruction_bool_not(IrAnalyze *ira, Stage1ZirInstBoolNot *instruction) {
20916 Stage1AirInst *value = instruction->value->child;
20917 if (type_is_invalid(value->value->type))
20918 return ira->codegen->invalid_inst_gen;
20919
20920 ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
20921
20922 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, bool_type);
20923 if (type_is_invalid(casted_value->value->type))
20924 return ira->codegen->invalid_inst_gen;
20925
20926 if (instr_is_comptime(casted_value)) {
20927 ZigValue *value = ir_resolve_const(ira, casted_value, UndefBad);
20928 if (value == nullptr)
20929 return ira->codegen->invalid_inst_gen;
20930
20931 return ir_const_bool(ira, instruction->base.scope, instruction->base.source_node, !value->data.x_bool);
20932 }
20933
20934 return ir_build_bool_not_gen(ira, instruction->base.scope, instruction->base.source_node, casted_value);
20935}
20936
20937static Stage1AirInst *ir_analyze_instruction_memset(IrAnalyze *ira, Stage1ZirInstMemset *instruction) {
20938 Error err;
20939
20940 Stage1AirInst *dest_ptr = instruction->dest_ptr->child;
20941 if (type_is_invalid(dest_ptr->value->type))
20942 return ira->codegen->invalid_inst_gen;
20943
20944 Stage1AirInst *byte_value = instruction->byte->child;
20945 if (type_is_invalid(byte_value->value->type))
20946 return ira->codegen->invalid_inst_gen;
20947
20948 Stage1AirInst *count_value = instruction->count->child;
20949 if (type_is_invalid(count_value->value->type))
20950 return ira->codegen->invalid_inst_gen;
20951
20952 ZigType *dest_uncasted_type = dest_ptr->value->type;
20953 bool dest_is_volatile = (dest_uncasted_type->id == ZigTypeIdPointer) &&
20954 dest_uncasted_type->data.pointer.is_volatile;
20955
20956 ZigType *usize = ira->codegen->builtin_types.entry_usize;
20957 ZigType *u8 = ira->codegen->builtin_types.entry_u8;
20958 uint32_t dest_align;
20959 if (dest_uncasted_type->id == ZigTypeIdPointer) {
20960 if ((err = resolve_ptr_align(ira, dest_uncasted_type, &dest_align)))
20961 return ira->codegen->invalid_inst_gen;
20962 } else {
20963 dest_align = get_abi_alignment(ira->codegen, u8);
20964 }
20965 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,
20966 PtrLenUnknown, dest_align, 0, 0, false);
20967
20968 Stage1AirInst *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr);
20969 if (type_is_invalid(casted_dest_ptr->value->type))
20970 return ira->codegen->invalid_inst_gen;
20971
20972 Stage1AirInst *casted_byte = ir_implicit_cast(ira, byte_value, u8);
20973 if (type_is_invalid(casted_byte->value->type))
20974 return ira->codegen->invalid_inst_gen;
20975
20976 Stage1AirInst *casted_count = ir_implicit_cast(ira, count_value, usize);
20977 if (type_is_invalid(casted_count->value->type))
20978 return ira->codegen->invalid_inst_gen;
20979
20980 // TODO test this at comptime with u8 and non-u8 types
20981 if (instr_is_comptime(casted_dest_ptr) &&
20982 instr_is_comptime(casted_byte) &&
20983 instr_is_comptime(casted_count))
20984 {
20985 ZigValue *dest_ptr_val = ir_resolve_const(ira, casted_dest_ptr, UndefBad);
20986 if (dest_ptr_val == nullptr)
20987 return ira->codegen->invalid_inst_gen;
20988
20989 ZigValue *byte_val = ir_resolve_const(ira, casted_byte, UndefOk);
20990 if (byte_val == nullptr)
20991 return ira->codegen->invalid_inst_gen;
20992
20993 ZigValue *count_val = ir_resolve_const(ira, casted_count, UndefBad);
20994 if (count_val == nullptr)
20995 return ira->codegen->invalid_inst_gen;
20996
20997 if (casted_dest_ptr->value->data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
20998 casted_dest_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar)
20999 {
21000 ZigValue *dest_elements;
21001 size_t start;
21002 size_t bound_end;
21003 switch (dest_ptr_val->data.x_ptr.special) {
21004 case ConstPtrSpecialInvalid:
21005 case ConstPtrSpecialDiscard:
21006 zig_unreachable();
21007 case ConstPtrSpecialRef:
21008 dest_elements = dest_ptr_val->data.x_ptr.data.ref.pointee;
21009 start = 0;
21010 bound_end = 1;
21011 break;
21012 case ConstPtrSpecialSubArray:
21013 case ConstPtrSpecialBaseArray:
21014 {
21015 ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
21016 expand_undef_array(ira->codegen, array_val);
21017 dest_elements = array_val->data.x_array.data.s_none.elements;
21018 start = dest_ptr_val->data.x_ptr.data.base_array.elem_index;
21019 bound_end = array_val->type->data.array.len;
21020 break;
21021 }
21022 case ConstPtrSpecialBaseStruct:
21023 zig_panic("TODO memset on const inner struct");
21024 case ConstPtrSpecialBaseErrorUnionCode:
21025 zig_panic("TODO memset on const inner error union code");
21026 case ConstPtrSpecialBaseErrorUnionPayload:
21027 zig_panic("TODO memset on const inner error union payload");
21028 case ConstPtrSpecialBaseOptionalPayload:
21029 zig_panic("TODO memset on const inner optional payload");
21030 case ConstPtrSpecialHardCodedAddr:
21031 zig_unreachable();
21032 case ConstPtrSpecialFunction:
21033 zig_panic("TODO memset on ptr cast from function");
21034 case ConstPtrSpecialNull:
21035 zig_panic("TODO memset on null ptr");
21036 }
21037
21038 size_t count = bigint_as_usize(&count_val->data.x_bigint);
21039 size_t end = start + count;
21040 if (end > bound_end) {
21041 ir_add_error(ira, count_value, buf_sprintf("out of bounds pointer access"));
21042 return ira->codegen->invalid_inst_gen;
21043 }
21044
21045 for (size_t i = start; i < end; i += 1) {
21046 copy_const_val(ira->codegen, &dest_elements[i], byte_val);
21047 }
21048
21049 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
21050 }
21051 }
21052
21053 return ir_build_memset_gen(ira, instruction->base.scope, instruction->base.source_node, casted_dest_ptr, casted_byte, casted_count);
21054}
21055
21056static Stage1AirInst *ir_analyze_instruction_memcpy(IrAnalyze *ira, Stage1ZirInstMemcpy *instruction) {
21057 Error err;
21058
21059 Stage1AirInst *dest_ptr = instruction->dest_ptr->child;
21060 if (type_is_invalid(dest_ptr->value->type))
21061 return ira->codegen->invalid_inst_gen;
21062
21063 Stage1AirInst *src_ptr = instruction->src_ptr->child;
21064 if (type_is_invalid(src_ptr->value->type))
21065 return ira->codegen->invalid_inst_gen;
21066
21067 Stage1AirInst *count_value = instruction->count->child;
21068 if (type_is_invalid(count_value->value->type))
21069 return ira->codegen->invalid_inst_gen;
21070
21071 ZigType *u8 = ira->codegen->builtin_types.entry_u8;
21072 ZigType *dest_uncasted_type = dest_ptr->value->type;
21073 ZigType *src_uncasted_type = src_ptr->value->type;
21074 bool dest_is_volatile = (dest_uncasted_type->id == ZigTypeIdPointer) &&
21075 dest_uncasted_type->data.pointer.is_volatile;
21076 bool src_is_volatile = (src_uncasted_type->id == ZigTypeIdPointer) &&
21077 src_uncasted_type->data.pointer.is_volatile;
21078
21079 uint32_t dest_align;
21080 if (dest_uncasted_type->id == ZigTypeIdPointer) {
21081 if ((err = resolve_ptr_align(ira, dest_uncasted_type, &dest_align)))
21082 return ira->codegen->invalid_inst_gen;
21083 } else {
21084 dest_align = get_abi_alignment(ira->codegen, u8);
21085 }
21086
21087 uint32_t src_align;
21088 if (src_uncasted_type->id == ZigTypeIdPointer) {
21089 if ((err = resolve_ptr_align(ira, src_uncasted_type, &src_align)))
21090 return ira->codegen->invalid_inst_gen;
21091 } else {
21092 src_align = get_abi_alignment(ira->codegen, u8);
21093 }
21094
21095 ZigType *usize = ira->codegen->builtin_types.entry_usize;
21096 ZigType *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,
21097 PtrLenUnknown, dest_align, 0, 0, false);
21098 ZigType *u8_ptr_const = get_pointer_to_type_extra(ira->codegen, u8, true, src_is_volatile,
21099 PtrLenUnknown, src_align, 0, 0, false);
21100
21101 Stage1AirInst *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr_mut);
21102 if (type_is_invalid(casted_dest_ptr->value->type))
21103 return ira->codegen->invalid_inst_gen;
21104
21105 Stage1AirInst *casted_src_ptr = ir_implicit_cast(ira, src_ptr, u8_ptr_const);
21106 if (type_is_invalid(casted_src_ptr->value->type))
21107 return ira->codegen->invalid_inst_gen;
21108
21109 Stage1AirInst *casted_count = ir_implicit_cast(ira, count_value, usize);
21110 if (type_is_invalid(casted_count->value->type))
21111 return ira->codegen->invalid_inst_gen;
21112
21113 // TODO test this at comptime with u8 and non-u8 types
21114 // TODO test with dest ptr being a global runtime variable
21115 if (instr_is_comptime(casted_dest_ptr) &&
21116 instr_is_comptime(casted_src_ptr) &&
21117 instr_is_comptime(casted_count))
21118 {
21119 ZigValue *dest_ptr_val = ir_resolve_const(ira, casted_dest_ptr, UndefBad);
21120 if (dest_ptr_val == nullptr)
21121 return ira->codegen->invalid_inst_gen;
21122
21123 ZigValue *src_ptr_val = ir_resolve_const(ira, casted_src_ptr, UndefBad);
21124 if (src_ptr_val == nullptr)
21125 return ira->codegen->invalid_inst_gen;
21126
21127 ZigValue *count_val = ir_resolve_const(ira, casted_count, UndefBad);
21128 if (count_val == nullptr)
21129 return ira->codegen->invalid_inst_gen;
21130
21131 if (dest_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
21132 size_t count = bigint_as_usize(&count_val->data.x_bigint);
21133
21134 ZigValue *dest_elements;
21135 size_t dest_start;
21136 size_t dest_end;
21137 switch (dest_ptr_val->data.x_ptr.special) {
21138 case ConstPtrSpecialInvalid:
21139 case ConstPtrSpecialDiscard:
21140 zig_unreachable();
21141 case ConstPtrSpecialRef:
21142 dest_elements = dest_ptr_val->data.x_ptr.data.ref.pointee;
21143 dest_start = 0;
21144 dest_end = 1;
21145 break;
21146 case ConstPtrSpecialSubArray:
21147 case ConstPtrSpecialBaseArray:
21148 {
21149 ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
21150 expand_undef_array(ira->codegen, array_val);
21151 dest_elements = array_val->data.x_array.data.s_none.elements;
21152 dest_start = dest_ptr_val->data.x_ptr.data.base_array.elem_index;
21153 dest_end = array_val->type->data.array.len;
21154 break;
21155 }
21156 case ConstPtrSpecialBaseStruct:
21157 zig_panic("TODO memcpy on const inner struct");
21158 case ConstPtrSpecialBaseErrorUnionCode:
21159 zig_panic("TODO memcpy on const inner error union code");
21160 case ConstPtrSpecialBaseErrorUnionPayload:
21161 zig_panic("TODO memcpy on const inner error union payload");
21162 case ConstPtrSpecialBaseOptionalPayload:
21163 zig_panic("TODO memcpy on const inner optional payload");
21164 case ConstPtrSpecialHardCodedAddr:
21165 zig_unreachable();
21166 case ConstPtrSpecialFunction:
21167 zig_panic("TODO memcpy on ptr cast from function");
21168 case ConstPtrSpecialNull:
21169 zig_panic("TODO memcpy on null ptr");
21170 }
21171
21172 if (dest_start + count > dest_end) {
21173 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("out of bounds pointer access"));
21174 return ira->codegen->invalid_inst_gen;
21175 }
21176
21177 ZigValue *src_elements;
21178 size_t src_start;
21179 size_t src_end;
21180
21181 switch (src_ptr_val->data.x_ptr.special) {
21182 case ConstPtrSpecialInvalid:
21183 case ConstPtrSpecialDiscard:
21184 zig_unreachable();
21185 case ConstPtrSpecialRef:
21186 src_elements = src_ptr_val->data.x_ptr.data.ref.pointee;
21187 src_start = 0;
21188 src_end = 1;
21189 break;
21190 case ConstPtrSpecialSubArray:
21191 case ConstPtrSpecialBaseArray:
21192 {
21193 ZigValue *array_val = src_ptr_val->data.x_ptr.data.base_array.array_val;
21194 expand_undef_array(ira->codegen, array_val);
21195 src_elements = array_val->data.x_array.data.s_none.elements;
21196 src_start = src_ptr_val->data.x_ptr.data.base_array.elem_index;
21197 src_end = array_val->type->data.array.len;
21198 break;
21199 }
21200 case ConstPtrSpecialBaseStruct:
21201 zig_panic("TODO memcpy on const inner struct");
21202 case ConstPtrSpecialBaseErrorUnionCode:
21203 zig_panic("TODO memcpy on const inner error union code");
21204 case ConstPtrSpecialBaseErrorUnionPayload:
21205 zig_panic("TODO memcpy on const inner error union payload");
21206 case ConstPtrSpecialBaseOptionalPayload:
21207 zig_panic("TODO memcpy on const inner optional payload");
21208 case ConstPtrSpecialHardCodedAddr:
21209 zig_unreachable();
21210 case ConstPtrSpecialFunction:
21211 zig_panic("TODO memcpy on ptr cast from function");
21212 case ConstPtrSpecialNull:
21213 zig_panic("TODO memcpy on null ptr");
21214 }
21215
21216 if (src_start + count > src_end) {
21217 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("out of bounds pointer access"));
21218 return ira->codegen->invalid_inst_gen;
21219 }
21220
21221 // TODO check for noalias violations - this should be generalized to work for any function
21222
21223 for (size_t i = 0; i < count; i += 1) {
21224 copy_const_val(ira->codegen, &dest_elements[dest_start + i], &src_elements[src_start + i]);
21225 }
21226
21227 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
21228 }
21229 }
21230
21231 return ir_build_memcpy_gen(ira, instruction->base.scope, instruction->base.source_node, casted_dest_ptr, casted_src_ptr, casted_count);
21232}
21233
21234static ZigType *get_result_loc_type(IrAnalyze *ira, ResultLoc *result_loc) {
21235 if (result_loc == nullptr) return nullptr;
21236
21237 if (result_loc->id == ResultLocIdCast) {
21238 return ir_resolve_type(ira, result_loc->source_instruction->child);
21239 }
21240
21241 return nullptr;
21242}
21243
21244static Stage1AirInst *ir_analyze_instruction_slice(IrAnalyze *ira, Stage1ZirInstSlice *instruction) {
21245 Error err;
21246
21247 Stage1AirInst *ptr_ptr = instruction->ptr->child;
21248 if (type_is_invalid(ptr_ptr->value->type))
21249 return ira->codegen->invalid_inst_gen;
21250
21251 ZigType *ptr_ptr_type = ptr_ptr->value->type;
21252 assert(ptr_ptr_type->id == ZigTypeIdPointer);
21253 ZigType *array_type = ptr_ptr_type->data.pointer.child_type;
21254
21255 Stage1AirInst *start = instruction->start->child;
21256 if (type_is_invalid(start->value->type))
21257 return ira->codegen->invalid_inst_gen;
21258
21259 ZigType *usize = ira->codegen->builtin_types.entry_usize;
21260 Stage1AirInst *casted_start = ir_implicit_cast(ira, start, usize);
21261 if (type_is_invalid(casted_start->value->type))
21262 return ira->codegen->invalid_inst_gen;
21263
21264 Stage1AirInst *end;
21265 if (instruction->end) {
21266 end = instruction->end->child;
21267 if (type_is_invalid(end->value->type))
21268 return ira->codegen->invalid_inst_gen;
21269 end = ir_implicit_cast(ira, end, usize);
21270 if (type_is_invalid(end->value->type))
21271 return ira->codegen->invalid_inst_gen;
21272 } else {
21273 end = nullptr;
21274 }
21275
21276 ZigValue *slice_sentinel_val = nullptr;
21277 ZigType *non_sentinel_slice_ptr_type;
21278 ZigType *elem_type;
21279
21280 bool generate_non_null_assert = false;
21281
21282 if (array_type->id == ZigTypeIdArray) {
21283 elem_type = array_type->data.array.child_type;
21284 non_sentinel_slice_ptr_type = get_pointer_to_type_extra(ira->codegen, elem_type,
21285 ptr_ptr_type->data.pointer.is_const,
21286 ptr_ptr_type->data.pointer.is_volatile,
21287 PtrLenUnknown,
21288 ptr_ptr_type->data.pointer.explicit_alignment, 0, 0, false);
21289 } else if (array_type->id == ZigTypeIdPointer) {
21290 if (array_type->data.pointer.ptr_len == PtrLenSingle) {
21291 ZigType *main_type = array_type->data.pointer.child_type;
21292 if (main_type->id == ZigTypeIdArray) {
21293 elem_type = main_type->data.pointer.child_type;
21294 non_sentinel_slice_ptr_type = get_pointer_to_type_extra(ira->codegen,
21295 elem_type,
21296 array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,
21297 PtrLenUnknown,
21298 array_type->data.pointer.explicit_alignment, 0, 0, false);
21299 } else {
21300 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("slice of single-item pointer"));
21301 return ira->codegen->invalid_inst_gen;
21302 }
21303 } else {
21304 elem_type = array_type->data.pointer.child_type;
21305 if (array_type->data.pointer.ptr_len == PtrLenC) {
21306 array_type = adjust_ptr_len(ira->codegen, array_type, PtrLenUnknown);
21307
21308 // C pointers are allowzero by default.
21309 // However, we want to be able to slice them without generating an allowzero slice (see issue #4401).
21310 // To achieve this, we generate a runtime safety check and make the slice type non-allowzero.
21311 if (array_type->data.pointer.allow_zero) {
21312 array_type = adjust_ptr_allow_zero(ira->codegen, array_type, false);
21313 generate_non_null_assert = true;
21314 }
21315 }
21316 ZigType *maybe_sentineled_slice_ptr_type = array_type;
21317 non_sentinel_slice_ptr_type = adjust_ptr_sentinel(ira->codegen, maybe_sentineled_slice_ptr_type, nullptr);
21318 if (!end) {
21319 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("slice of pointer must include end value"));
21320 return ira->codegen->invalid_inst_gen;
21321 }
21322 }
21323 } else if (is_slice(array_type)) {
21324 ZigType *maybe_sentineled_slice_ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
21325 slice_sentinel_val = maybe_sentineled_slice_ptr_type->data.pointer.sentinel;
21326 non_sentinel_slice_ptr_type = adjust_ptr_sentinel(ira->codegen, maybe_sentineled_slice_ptr_type, nullptr);
21327 elem_type = non_sentinel_slice_ptr_type->data.pointer.child_type;
21328 } else {
21329 ir_add_error_node(ira, instruction->base.source_node,
21330 buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name)));
21331 return ira->codegen->invalid_inst_gen;
21332 }
21333
21334 ZigValue *sentinel_val = nullptr;
21335 if (instruction->sentinel) {
21336 Stage1AirInst *uncasted_sentinel = instruction->sentinel->child;
21337 if (type_is_invalid(uncasted_sentinel->value->type))
21338 return ira->codegen->invalid_inst_gen;
21339 Stage1AirInst *sentinel = ir_implicit_cast(ira, uncasted_sentinel, elem_type);
21340 if (type_is_invalid(sentinel->value->type))
21341 return ira->codegen->invalid_inst_gen;
21342 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
21343 if (sentinel_val == nullptr)
21344 return ira->codegen->invalid_inst_gen;
21345 }
21346
21347 ZigType *child_array_type = (array_type->id == ZigTypeIdPointer &&
21348 array_type->data.pointer.ptr_len == PtrLenSingle) ? array_type->data.pointer.child_type : array_type;
21349
21350 ZigType *return_type;
21351
21352 // If start index and end index are both comptime known, then the result type is a pointer to array
21353 // not a slice. However, if the start or end index is a lazy value, and the result location is a slice,
21354 // then the pointer-to-array would be casted to a slice anyway. So, we preserve the laziness of these
21355 // values by making the return type a slice.
21356 ZigType *res_loc_type = get_result_loc_type(ira, instruction->result_loc);
21357 bool result_loc_is_slice = (res_loc_type != nullptr && is_slice(res_loc_type));
21358 bool end_is_known = !result_loc_is_slice &&
21359 ((end != nullptr && value_is_comptime(end->value)) ||
21360 (end == nullptr && child_array_type->id == ZigTypeIdArray));
21361
21362 ZigValue *array_sentinel = sentinel_val;
21363 if (end_is_known) {
21364 uint64_t end_scalar;
21365 if (end != nullptr) {
21366 ZigValue *end_val = ir_resolve_const(ira, end, UndefBad);
21367 if (!end_val)
21368 return ira->codegen->invalid_inst_gen;
21369 end_scalar = bigint_as_u64(&end_val->data.x_bigint);
21370 } else {
21371 end_scalar = child_array_type->data.array.len;
21372 }
21373 array_sentinel = (child_array_type->id == ZigTypeIdArray && end_scalar == child_array_type->data.array.len)
21374 ? child_array_type->data.array.sentinel : sentinel_val;
21375
21376 if (value_is_comptime(casted_start->value)) {
21377 ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad);
21378 if (!start_val)
21379 return ira->codegen->invalid_inst_gen;
21380
21381 uint64_t start_scalar = bigint_as_u64(&start_val->data.x_bigint);
21382
21383 if (start_scalar > end_scalar) {
21384 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("out of bounds slice"));
21385 return ira->codegen->invalid_inst_gen;
21386 }
21387
21388 uint32_t base_ptr_align = non_sentinel_slice_ptr_type->data.pointer.explicit_alignment;
21389 uint32_t ptr_byte_alignment = 0;
21390 if (end_scalar > start_scalar) {
21391 if ((err = compute_elem_align(ira, elem_type, base_ptr_align, start_scalar, &ptr_byte_alignment)))
21392 return ira->codegen->invalid_inst_gen;
21393 }
21394
21395 ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar,
21396 array_sentinel);
21397 return_type = get_pointer_to_type_extra(ira->codegen, return_array_type,
21398 non_sentinel_slice_ptr_type->data.pointer.is_const,
21399 non_sentinel_slice_ptr_type->data.pointer.is_volatile,
21400 PtrLenSingle, ptr_byte_alignment, 0, 0, false);
21401 goto done_with_return_type;
21402 }
21403 } else if (array_sentinel == nullptr && end == nullptr) {
21404 array_sentinel = slice_sentinel_val;
21405 }
21406 if (array_sentinel != nullptr) {
21407 // TODO deal with non-abi-alignment here
21408 ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, array_sentinel);
21409 return_type = get_slice_type(ira->codegen, slice_ptr_type);
21410 } else {
21411 // TODO deal with non-abi-alignment here
21412 return_type = get_slice_type(ira->codegen, non_sentinel_slice_ptr_type);
21413 }
21414done_with_return_type:
21415
21416 if (instr_is_comptime(ptr_ptr) &&
21417 value_is_comptime(casted_start->value) &&
21418 (!end || value_is_comptime(end->value)))
21419 {
21420 ZigValue *array_val;
21421 ZigValue *parent_ptr;
21422 size_t abs_offset;
21423 size_t rel_end;
21424 bool ptr_is_undef = false;
21425 if (child_array_type->id == ZigTypeIdArray) {
21426 if (array_type->id == ZigTypeIdPointer) {
21427 parent_ptr = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.source_node);
21428 if (parent_ptr == nullptr)
21429 return ira->codegen->invalid_inst_gen;
21430
21431 if (parent_ptr->special == ConstValSpecialUndef) {
21432 array_val = nullptr;
21433 abs_offset = 0;
21434 rel_end = SIZE_MAX;
21435 ptr_is_undef = true;
21436 } else if (parent_ptr->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
21437 array_val = nullptr;
21438 abs_offset = 0;
21439 rel_end = SIZE_MAX;
21440 } else {
21441 array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.source_node);
21442 if (array_val == nullptr)
21443 return ira->codegen->invalid_inst_gen;
21444
21445 rel_end = child_array_type->data.array.len;
21446 abs_offset = 0;
21447 }
21448 } else {
21449 array_val = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.source_node);
21450 if (array_val == nullptr)
21451 return ira->codegen->invalid_inst_gen;
21452 rel_end = array_type->data.array.len;
21453 parent_ptr = nullptr;
21454 abs_offset = 0;
21455 }
21456 } else if (array_type->id == ZigTypeIdPointer) {
21457 assert(array_type->data.pointer.ptr_len == PtrLenUnknown);
21458 parent_ptr = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.source_node);
21459 if (parent_ptr == nullptr)
21460 return ira->codegen->invalid_inst_gen;
21461
21462 if (parent_ptr->special == ConstValSpecialUndef) {
21463 array_val = nullptr;
21464 abs_offset = 0;
21465 rel_end = SIZE_MAX;
21466 ptr_is_undef = true;
21467 } else switch (parent_ptr->data.x_ptr.special) {
21468 case ConstPtrSpecialInvalid:
21469 case ConstPtrSpecialDiscard:
21470 zig_unreachable();
21471 case ConstPtrSpecialRef:
21472 if (parent_ptr->data.x_ptr.data.ref.pointee->type->id == ZigTypeIdArray) {
21473 array_val = parent_ptr->data.x_ptr.data.ref.pointee;
21474 abs_offset = 0;
21475 rel_end = array_val->type->data.array.len;
21476 } else {
21477 array_val = nullptr;
21478 abs_offset = SIZE_MAX;
21479 rel_end = 1;
21480 }
21481 break;
21482 case ConstPtrSpecialSubArray:
21483 case ConstPtrSpecialBaseArray:
21484 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
21485 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;
21486 rel_end = array_val->type->data.array.len - abs_offset;
21487 break;
21488 case ConstPtrSpecialBaseStruct:
21489 zig_panic("TODO slice const inner struct");
21490 case ConstPtrSpecialBaseErrorUnionCode:
21491 zig_panic("TODO slice const inner error union code");
21492 case ConstPtrSpecialBaseErrorUnionPayload:
21493 zig_panic("TODO slice const inner error union payload");
21494 case ConstPtrSpecialBaseOptionalPayload:
21495 zig_panic("TODO slice const inner optional payload");
21496 case ConstPtrSpecialHardCodedAddr:
21497 array_val = nullptr;
21498 abs_offset = 0;
21499 rel_end = SIZE_MAX;
21500 break;
21501 case ConstPtrSpecialFunction:
21502 zig_panic("TODO slice of ptr cast from function");
21503 case ConstPtrSpecialNull:
21504 zig_panic("TODO slice of null ptr");
21505 }
21506 } else if (is_slice(array_type)) {
21507 ZigValue *slice_ptr = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.source_node);
21508 if (slice_ptr == nullptr)
21509 return ira->codegen->invalid_inst_gen;
21510
21511 if (slice_ptr->special == ConstValSpecialUndef) {
21512 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("slice of undefined"));
21513 return ira->codegen->invalid_inst_gen;
21514 }
21515
21516 parent_ptr = slice_ptr->data.x_struct.fields[slice_ptr_index];
21517 if (parent_ptr->special == ConstValSpecialUndef) {
21518 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("slice of undefined"));
21519 return ira->codegen->invalid_inst_gen;
21520 }
21521
21522 ZigValue *len_val = slice_ptr->data.x_struct.fields[slice_len_index];
21523
21524 switch (parent_ptr->data.x_ptr.special) {
21525 case ConstPtrSpecialInvalid:
21526 case ConstPtrSpecialDiscard:
21527 zig_unreachable();
21528 case ConstPtrSpecialRef:
21529 array_val = nullptr;
21530 abs_offset = SIZE_MAX;
21531 rel_end = 1;
21532 break;
21533 case ConstPtrSpecialSubArray:
21534 case ConstPtrSpecialBaseArray:
21535 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
21536 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;
21537 rel_end = bigint_as_usize(&len_val->data.x_bigint);
21538 break;
21539 case ConstPtrSpecialBaseStruct:
21540 zig_panic("TODO slice const inner struct");
21541 case ConstPtrSpecialBaseErrorUnionCode:
21542 zig_panic("TODO slice const inner error union code");
21543 case ConstPtrSpecialBaseErrorUnionPayload:
21544 zig_panic("TODO slice const inner error union payload");
21545 case ConstPtrSpecialBaseOptionalPayload:
21546 zig_panic("TODO slice const inner optional payload");
21547 case ConstPtrSpecialHardCodedAddr:
21548 array_val = nullptr;
21549 abs_offset = 0;
21550 rel_end = bigint_as_usize(&len_val->data.x_bigint);
21551 break;
21552 case ConstPtrSpecialFunction:
21553 zig_panic("TODO slice of slice cast from function");
21554 case ConstPtrSpecialNull:
21555 zig_panic("TODO slice of null");
21556 }
21557 } else {
21558 zig_unreachable();
21559 }
21560
21561 ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad);
21562 if (!start_val)
21563 return ira->codegen->invalid_inst_gen;
21564
21565 uint64_t start_scalar = bigint_as_u64(&start_val->data.x_bigint);
21566 if (!ptr_is_undef && start_scalar > rel_end) {
21567 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("out of bounds slice"));
21568 return ira->codegen->invalid_inst_gen;
21569 }
21570
21571 uint64_t end_scalar = rel_end;
21572 if (end) {
21573 ZigValue *end_val = ir_resolve_const(ira, end, UndefBad);
21574 if (!end_val)
21575 return ira->codegen->invalid_inst_gen;
21576 end_scalar = bigint_as_u64(&end_val->data.x_bigint);
21577 }
21578 if (!ptr_is_undef) {
21579 if (end_scalar > rel_end) {
21580 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("out of bounds slice"));
21581 return ira->codegen->invalid_inst_gen;
21582 }
21583 if (start_scalar > end_scalar) {
21584 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("slice start is greater than end"));
21585 return ira->codegen->invalid_inst_gen;
21586 }
21587 }
21588 if (ptr_is_undef && start_scalar != end_scalar) {
21589 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("non-zero length slice of undefined pointer"));
21590 return ira->codegen->invalid_inst_gen;
21591 }
21592
21593 // check sentinel when target is comptime-known
21594 {
21595 if (!sentinel_val)
21596 goto exit_check_sentinel;
21597
21598 switch (ptr_ptr->value->data.x_ptr.mut) {
21599 case ConstPtrMutComptimeConst:
21600 case ConstPtrMutComptimeVar:
21601 break;
21602 case ConstPtrMutRuntimeVar:
21603 case ConstPtrMutInfer:
21604 goto exit_check_sentinel;
21605 }
21606
21607 // prepare check parameters
21608 ZigValue *target = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.source_node);
21609 if (target == nullptr)
21610 return ira->codegen->invalid_inst_gen;
21611
21612 uint64_t target_len = 0;
21613 ZigValue *target_sentinel = nullptr;
21614 ZigValue *target_elements = nullptr;
21615
21616 for (;;) {
21617 if (target->type->id == ZigTypeIdArray) {
21618 // handle `[N]T`
21619 target_len = target->type->data.array.len;
21620 target_sentinel = target->type->data.array.sentinel;
21621 expand_undef_array(ira->codegen, target);
21622 target_elements = target->data.x_array.data.s_none.elements;
21623 break;
21624 } else if (target->type->id == ZigTypeIdPointer && target->type->data.pointer.child_type->id == ZigTypeIdArray) {
21625 // handle `*[N]T`
21626 target = const_ptr_pointee(ira, ira->codegen, target, instruction->base.source_node);
21627 if (target == nullptr)
21628 return ira->codegen->invalid_inst_gen;
21629 assert(target->type->id == ZigTypeIdArray);
21630 continue;
21631 } else if (target->type->id == ZigTypeIdPointer) {
21632 // handle `[*]T`
21633 // handle `[*c]T`
21634 switch (target->data.x_ptr.special) {
21635 case ConstPtrSpecialInvalid:
21636 case ConstPtrSpecialDiscard:
21637 zig_unreachable();
21638 case ConstPtrSpecialRef:
21639 target = target->data.x_ptr.data.ref.pointee;
21640 assert(target->type->id == ZigTypeIdArray);
21641 continue;
21642 case ConstPtrSpecialBaseArray:
21643 case ConstPtrSpecialSubArray:
21644 target = target->data.x_ptr.data.base_array.array_val;
21645 assert(target->type->id == ZigTypeIdArray);
21646 continue;
21647 case ConstPtrSpecialBaseStruct:
21648 zig_panic("TODO slice const inner struct");
21649 case ConstPtrSpecialBaseErrorUnionCode:
21650 zig_panic("TODO slice const inner error union code");
21651 case ConstPtrSpecialBaseErrorUnionPayload:
21652 zig_panic("TODO slice const inner error union payload");
21653 case ConstPtrSpecialBaseOptionalPayload:
21654 zig_panic("TODO slice const inner optional payload");
21655 case ConstPtrSpecialHardCodedAddr:
21656 // skip check
21657 goto exit_check_sentinel;
21658 case ConstPtrSpecialFunction:
21659 zig_panic("TODO slice of ptr cast from function");
21660 case ConstPtrSpecialNull:
21661 zig_panic("TODO slice of null ptr");
21662 }
21663 break;
21664 } else if (is_slice(target->type)) {
21665 // handle `[]T`
21666 target = target->data.x_struct.fields[slice_ptr_index];
21667 assert(target->type->id == ZigTypeIdPointer);
21668 continue;
21669 }
21670
21671 zig_unreachable();
21672 }
21673
21674 // perform check
21675 if (target_sentinel == nullptr) {
21676 if (end_scalar >= target_len) {
21677 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("slice-sentinel is out of bounds"));
21678 return ira->codegen->invalid_inst_gen;
21679 }
21680 if (!const_values_equal(ira->codegen, sentinel_val, &target_elements[end_scalar])) {
21681 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("slice-sentinel does not match memory at target index"));
21682 return ira->codegen->invalid_inst_gen;
21683 }
21684 } else {
21685 assert(end_scalar <= target_len);
21686 if (end_scalar == target_len) {
21687 if (!const_values_equal(ira->codegen, sentinel_val, target_sentinel)) {
21688 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("slice-sentinel does not match target-sentinel"));
21689 return ira->codegen->invalid_inst_gen;
21690 }
21691 } else {
21692 if (!const_values_equal(ira->codegen, sentinel_val, &target_elements[end_scalar])) {
21693 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("slice-sentinel does not match memory at target index"));
21694 return ira->codegen->invalid_inst_gen;
21695 }
21696 }
21697 }
21698 }
21699 exit_check_sentinel:
21700
21701 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, return_type);
21702
21703 ZigValue *ptr_val;
21704 if (return_type->id == ZigTypeIdPointer) {
21705 // pointer to array
21706 ptr_val = result->value;
21707 } else {
21708 // slice
21709 result->value->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2);
21710
21711 ptr_val = result->value->data.x_struct.fields[slice_ptr_index];
21712
21713 ZigValue *len_val = result->value->data.x_struct.fields[slice_len_index];
21714 init_const_usize(ira->codegen, len_val, end_scalar - start_scalar);
21715 }
21716
21717 bool return_type_is_const = non_sentinel_slice_ptr_type->data.pointer.is_const;
21718 if (array_val) {
21719 size_t index = abs_offset + start_scalar;
21720 init_const_ptr_array(ira->codegen, ptr_val, array_val, index, return_type_is_const, PtrLenUnknown);
21721 if (return_type->id == ZigTypeIdPointer) {
21722 ptr_val->data.x_ptr.special = ConstPtrSpecialSubArray;
21723 }
21724 if (array_type->id == ZigTypeIdArray) {
21725 ptr_val->data.x_ptr.mut = ptr_ptr->value->data.x_ptr.mut;
21726 } else if (is_slice(array_type)) {
21727 ptr_val->data.x_ptr.mut = parent_ptr->data.x_ptr.mut;
21728 } else if (array_type->id == ZigTypeIdPointer) {
21729 ptr_val->data.x_ptr.mut = parent_ptr->data.x_ptr.mut;
21730 }
21731 } else if (ptr_is_undef) {
21732 ptr_val->type = get_pointer_to_type(ira->codegen, parent_ptr->type->data.pointer.child_type,
21733 return_type_is_const);
21734 ptr_val->special = ConstValSpecialUndef;
21735 } else switch (parent_ptr->data.x_ptr.special) {
21736 case ConstPtrSpecialInvalid:
21737 case ConstPtrSpecialDiscard:
21738 zig_unreachable();
21739 case ConstPtrSpecialRef:
21740 init_const_ptr_ref(ira->codegen, ptr_val, parent_ptr->data.x_ptr.data.ref.pointee,
21741 return_type_is_const);
21742 break;
21743 case ConstPtrSpecialSubArray:
21744 case ConstPtrSpecialBaseArray:
21745 zig_unreachable();
21746 case ConstPtrSpecialBaseStruct:
21747 zig_panic("TODO: ir_analyze_instruction_slice ConstPtrSpecialBaseStruct");
21748 case ConstPtrSpecialBaseErrorUnionCode:
21749 zig_panic("TODO: ir_analyze_instruction_slice ConstPtrSpecialBaseErrorUnionCode");
21750 case ConstPtrSpecialBaseErrorUnionPayload:
21751 zig_panic("TODO: ir_analyze_instruction_slice ConstPtrSpecialBaseErrorUnionPayload");
21752 case ConstPtrSpecialBaseOptionalPayload:
21753 zig_panic("TODO: ir_analyze_instruction_slice ConstPtrSpecialBaseOptionalPayload");
21754 case ConstPtrSpecialHardCodedAddr:
21755 init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,
21756 parent_ptr->type->data.pointer.child_type,
21757 parent_ptr->data.x_ptr.data.hard_coded_addr.addr + start_scalar,
21758 return_type_is_const);
21759 break;
21760 case ConstPtrSpecialFunction:
21761 zig_panic("TODO: ir_analyze_instruction_slice ConstPtrSpecialFunction");
21762 case ConstPtrSpecialNull:
21763 zig_panic("TODO: ir_analyze_instruction_slice ConstPtrSpecialNull");
21764 }
21765
21766 // In the case of pointer-to-array, we must restore this because above it overwrites ptr_val->type
21767 result->value->type = return_type;
21768 return result;
21769 }
21770
21771 if (generate_non_null_assert) {
21772 Stage1AirInst *ptr_val = ir_get_deref(ira, instruction->base.scope,
21773 instruction->base.source_node, ptr_ptr, nullptr);
21774
21775 if (type_is_invalid(ptr_val->value->type))
21776 return ira->codegen->invalid_inst_gen;
21777
21778 ir_build_assert_non_null(ira, instruction->base.scope, instruction->base.source_node, ptr_val);
21779 }
21780
21781 Stage1AirInst *result_loc = nullptr;
21782
21783 if (return_type->id != ZigTypeIdPointer) {
21784 result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
21785 return_type, nullptr, true, true);
21786 if (result_loc != nullptr) {
21787 if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
21788 return result_loc;
21789 }
21790
21791 src_assert(result_loc->value->type->id == ZigTypeIdPointer, instruction->base.source_node);
21792 if (result_loc->value->type->data.pointer.is_const) {
21793 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("cannot assign to constant"));
21794 return ira->codegen->invalid_inst_gen;
21795 }
21796
21797 Stage1AirInst *dummy_value = ir_const(ira, instruction->base.scope, instruction->base.source_node, return_type);
21798 dummy_value->value->special = ConstValSpecialRuntime;
21799 Stage1AirInst *dummy_result = ir_implicit_cast2(ira,
21800 instruction->base.scope, instruction->base.source_node,
21801 dummy_value, result_loc->value->type->data.pointer.child_type);
21802 if (type_is_invalid(dummy_result->value->type))
21803 return ira->codegen->invalid_inst_gen;
21804 }
21805 }
21806
21807 return ir_build_slice_gen(ira, instruction->base.scope, instruction->base.source_node, return_type, ptr_ptr,
21808 casted_start, end, instruction->safety_check_on, result_loc, sentinel_val);
21809}
21810
21811static Stage1AirInst *ir_analyze_instruction_has_field(IrAnalyze *ira, Stage1ZirInstHasField *instruction) {
21812 Error err;
21813 ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
21814 if (type_is_invalid(container_type))
21815 return ira->codegen->invalid_inst_gen;
21816
21817 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusZeroBitsKnown)))
21818 return ira->codegen->invalid_inst_gen;
21819
21820 Buf *field_name = ir_resolve_str(ira, instruction->field_name->child);
21821 if (field_name == nullptr)
21822 return ira->codegen->invalid_inst_gen;
21823
21824 bool result;
21825 if (container_type->id == ZigTypeIdStruct) {
21826 result = find_struct_type_field(container_type, field_name) != nullptr;
21827 } else if (container_type->id == ZigTypeIdEnum) {
21828 result = find_enum_type_field(container_type, field_name) != nullptr;
21829 } else if (container_type->id == ZigTypeIdUnion) {
21830 result = find_union_type_field(container_type, field_name) != nullptr;
21831 } else {
21832 ir_add_error_node(ira, instruction->container_type->source_node,
21833 buf_sprintf("type '%s' does not support @hasField", buf_ptr(&container_type->name)));
21834 return ira->codegen->invalid_inst_gen;
21835 }
21836 return ir_const_bool(ira, instruction->base.scope, instruction->base.source_node, result);
21837}
21838
21839static Stage1AirInst *ir_analyze_instruction_wasm_memory_size(IrAnalyze *ira, Stage1ZirInstWasmMemorySize *instruction) {
21840 // TODO generate compile error for target_arch different than 32bit
21841 if (!target_is_wasm(ira->codegen->zig_target)) {
21842 ir_add_error_node(ira, instruction->base.source_node,
21843 buf_sprintf("@wasmMemorySize is a wasm32 feature only"));
21844 return ira->codegen->invalid_inst_gen;
21845 }
21846
21847 Stage1AirInst *index = instruction->index->child;
21848 if (type_is_invalid(index->value->type))
21849 return ira->codegen->invalid_inst_gen;
21850
21851 ZigType *u32 = ira->codegen->builtin_types.entry_u32;
21852
21853 Stage1AirInst *casted_index = ir_implicit_cast(ira, index, u32);
21854 if (type_is_invalid(casted_index->value->type))
21855 return ira->codegen->invalid_inst_gen;
21856
21857 return ir_build_wasm_memory_size_gen(ira, instruction->base.scope, instruction->base.source_node, casted_index);
21858}
21859
21860static Stage1AirInst *ir_analyze_instruction_wasm_memory_grow(IrAnalyze *ira, Stage1ZirInstWasmMemoryGrow *instruction) {
21861 // TODO generate compile error for target_arch different than 32bit
21862 if (!target_is_wasm(ira->codegen->zig_target)) {
21863 ir_add_error_node(ira, instruction->base.source_node,
21864 buf_sprintf("@wasmMemoryGrow is a wasm32 feature only"));
21865 return ira->codegen->invalid_inst_gen;
21866 }
21867
21868 Stage1AirInst *index = instruction->index->child;
21869 if (type_is_invalid(index->value->type))
21870 return ira->codegen->invalid_inst_gen;
21871
21872 ZigType *u32 = ira->codegen->builtin_types.entry_u32;
21873
21874 Stage1AirInst *casted_index = ir_implicit_cast(ira, index, u32);
21875 if (type_is_invalid(casted_index->value->type))
21876 return ira->codegen->invalid_inst_gen;
21877
21878 Stage1AirInst *delta = instruction->delta->child;
21879 if (type_is_invalid(delta->value->type))
21880 return ira->codegen->invalid_inst_gen;
21881
21882 Stage1AirInst *casted_delta = ir_implicit_cast(ira, delta, u32);
21883 if (type_is_invalid(casted_delta->value->type))
21884 return ira->codegen->invalid_inst_gen;
21885
21886 return ir_build_wasm_memory_grow_gen(ira, instruction->base.scope, instruction->base.source_node, casted_index, casted_delta);
21887}
21888
21889static Stage1AirInst *ir_analyze_instruction_breakpoint(IrAnalyze *ira, Stage1ZirInstBreakpoint *instruction) {
21890 return ir_build_breakpoint_gen(ira, instruction->base.scope, instruction->base.source_node);
21891}
21892
21893static Stage1AirInst *ir_analyze_instruction_return_address(IrAnalyze *ira, Stage1ZirInstReturnAddress *instruction) {
21894 return ir_build_return_address_gen(ira, instruction->base.scope, instruction->base.source_node);
21895}
21896
21897static Stage1AirInst *ir_analyze_instruction_frame_address(IrAnalyze *ira, Stage1ZirInstFrameAddress *instruction) {
21898 return ir_build_frame_address_gen(ira, instruction->base.scope, instruction->base.source_node);
21899}
21900
21901static Stage1AirInst *ir_analyze_instruction_frame_handle(IrAnalyze *ira, Stage1ZirInstFrameHandle *instruction) {
21902 ZigFn *fn = ira->fn;
21903 src_assert(fn != nullptr, instruction->base.source_node);
21904
21905 if (fn->inferred_async_node == nullptr) {
21906 fn->inferred_async_node = instruction->base.source_node;
21907 }
21908
21909 ZigType *frame_type = get_fn_frame_type(ira->codegen, fn);
21910 ZigType *ptr_frame_type = get_pointer_to_type(ira->codegen, frame_type, false);
21911
21912 return ir_build_handle_gen(ira, instruction->base.scope, instruction->base.source_node, ptr_frame_type);
21913}
21914
21915static Stage1AirInst *ir_analyze_instruction_frame_type(IrAnalyze *ira, Stage1ZirInstFrameType *instruction) {
21916 ZigFn *fn = ir_resolve_fn(ira, instruction->fn->child);
21917 if (fn == nullptr)
21918 return ira->codegen->invalid_inst_gen;
21919
21920 if (fn->type_entry->data.fn.is_generic) {
21921 ir_add_error_node(ira, instruction->base.source_node,
21922 buf_sprintf("@Frame() of generic function"));
21923 return ira->codegen->invalid_inst_gen;
21924 }
21925
21926 ZigType *ty = get_fn_frame_type(ira->codegen, fn);
21927 return ir_const_type(ira, instruction->base.scope, instruction->base.source_node, ty);
21928}
21929
21930static Stage1AirInst *ir_analyze_instruction_frame_size(IrAnalyze *ira, Stage1ZirInstFrameSize *instruction) {
21931 Stage1AirInst *fn = instruction->fn->child;
21932 if (type_is_invalid(fn->value->type))
21933 return ira->codegen->invalid_inst_gen;
21934
21935 if (fn->value->type->id != ZigTypeIdFn) {
21936 ir_add_error(ira, fn,
21937 buf_sprintf("expected function, found '%s'", buf_ptr(&fn->value->type->name)));
21938 return ira->codegen->invalid_inst_gen;
21939 }
21940
21941 ira->codegen->need_frame_size_prefix_data = true;
21942
21943 return ir_build_frame_size_gen(ira, instruction->base.scope, instruction->base.source_node, fn);
21944}
21945
21946static Stage1AirInst *ir_analyze_instruction_align_of(IrAnalyze *ira, Stage1ZirInstAlignOf *instruction) {
21947 // Here we create a lazy value in order to avoid resolving the alignment of the type
21948 // immediately. This avoids false positive dependency loops such as:
21949 // const Node = struct {
21950 // field: []align(@alignOf(Node)) Node,
21951 // };
21952 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int);
21953 result->value->special = ConstValSpecialLazy;
21954
21955 LazyValueAlignOf *lazy_align_of = heap::c_allocator.create<LazyValueAlignOf>();
21956 lazy_align_of->ira = ira; ira_ref(ira);
21957 result->value->data.x_lazy = &lazy_align_of->base;
21958 lazy_align_of->base.id = LazyValueIdAlignOf;
21959
21960 lazy_align_of->target_type = instruction->type_value->child;
21961 if (ir_resolve_type_lazy(ira, lazy_align_of->target_type) == nullptr)
21962 return ira->codegen->invalid_inst_gen;
21963
21964 return result;
21965}
21966
21967static Stage1AirInst *ir_analyze_instruction_overflow_op(IrAnalyze *ira, Stage1ZirInstOverflowOp *instruction) {
21968 Error err;
21969
21970 Stage1AirInst *type_value = instruction->type_value->child;
21971 if (type_is_invalid(type_value->value->type))
21972 return ira->codegen->invalid_inst_gen;
21973
21974 ZigType *dest_type = ir_resolve_type(ira, type_value);
21975 if (type_is_invalid(dest_type))
21976 return ira->codegen->invalid_inst_gen;
21977
21978 if (dest_type->id != ZigTypeIdInt) {
21979 ir_add_error(ira, type_value,
21980 buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));
21981 return ira->codegen->invalid_inst_gen;
21982 }
21983
21984 Stage1AirInst *op1 = instruction->op1->child;
21985 if (type_is_invalid(op1->value->type))
21986 return ira->codegen->invalid_inst_gen;
21987
21988 Stage1AirInst *casted_op1 = ir_implicit_cast(ira, op1, dest_type);
21989 if (type_is_invalid(casted_op1->value->type))
21990 return ira->codegen->invalid_inst_gen;
21991
21992 Stage1AirInst *op2 = instruction->op2->child;
21993 if (type_is_invalid(op2->value->type))
21994 return ira->codegen->invalid_inst_gen;
21995
21996 Stage1AirInst *casted_op2;
21997 if (instruction->op == IrOverflowOpShl) {
21998 ZigType *shift_amt_type = get_smallest_unsigned_int_type(ira->codegen,
21999 dest_type->data.integral.bit_count - 1);
22000 casted_op2 = ir_implicit_cast(ira, op2, shift_amt_type);
22001 } else {
22002 casted_op2 = ir_implicit_cast(ira, op2, dest_type);
22003 }
22004 if (type_is_invalid(casted_op2->value->type))
22005 return ira->codegen->invalid_inst_gen;
22006
22007 Stage1AirInst *result_ptr = instruction->result_ptr->child;
22008 if (type_is_invalid(result_ptr->value->type))
22009 return ira->codegen->invalid_inst_gen;
22010
22011 ZigType *expected_ptr_type;
22012 if (result_ptr->value->type->id == ZigTypeIdPointer) {
22013 uint32_t alignment;
22014 if ((err = resolve_ptr_align(ira, result_ptr->value->type, &alignment)))
22015 return ira->codegen->invalid_inst_gen;
22016 expected_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_type,
22017 false, result_ptr->value->type->data.pointer.is_volatile,
22018 PtrLenSingle,
22019 alignment, 0, 0, false);
22020 } else {
22021 expected_ptr_type = get_pointer_to_type(ira->codegen, dest_type, false);
22022 }
22023
22024 Stage1AirInst *casted_result_ptr = ir_implicit_cast(ira, result_ptr, expected_ptr_type);
22025 if (type_is_invalid(casted_result_ptr->value->type))
22026 return ira->codegen->invalid_inst_gen;
22027
22028 // Don't write anything to the result pointer.
22029 if (dest_type->data.integral.bit_count == 0)
22030 return ir_const_bool(ira, instruction->base.scope, instruction->base.source_node, false);
22031
22032 if (instr_is_comptime(casted_op1) &&
22033 instr_is_comptime(casted_op2) &&
22034 instr_is_comptime(casted_result_ptr))
22035 {
22036 ZigValue *op1_val = ir_resolve_const(ira, casted_op1, UndefBad);
22037 if (op1_val == nullptr)
22038 return ira->codegen->invalid_inst_gen;
22039
22040 ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
22041 if (op2_val == nullptr)
22042 return ira->codegen->invalid_inst_gen;
22043
22044 ZigValue *result_val = ir_resolve_const(ira, casted_result_ptr, UndefBad);
22045 if (result_val == nullptr)
22046 return ira->codegen->invalid_inst_gen;
22047
22048 BigInt *op1_bigint = &op1_val->data.x_bigint;
22049 BigInt *op2_bigint = &op2_val->data.x_bigint;
22050 ZigValue *pointee_val = const_ptr_pointee(ira, ira->codegen, result_val,
22051 casted_result_ptr->source_node);
22052 if (pointee_val == nullptr)
22053 return ira->codegen->invalid_inst_gen;
22054 BigInt *dest_bigint = &pointee_val->data.x_bigint;
22055 switch (instruction->op) {
22056 case IrOverflowOpAdd:
22057 bigint_add(dest_bigint, op1_bigint, op2_bigint);
22058 break;
22059 case IrOverflowOpSub:
22060 bigint_sub(dest_bigint, op1_bigint, op2_bigint);
22061 break;
22062 case IrOverflowOpMul:
22063 bigint_mul(dest_bigint, op1_bigint, op2_bigint);
22064 break;
22065 case IrOverflowOpShl:
22066 bigint_shl(dest_bigint, op1_bigint, op2_bigint);
22067 break;
22068 }
22069 bool result_bool = false;
22070 if (!bigint_fits_in_bits(dest_bigint, dest_type->data.integral.bit_count,
22071 dest_type->data.integral.is_signed))
22072 {
22073 result_bool = true;
22074 BigInt tmp_bigint;
22075 bigint_init_bigint(&tmp_bigint, dest_bigint);
22076 bigint_truncate(dest_bigint, &tmp_bigint, dest_type->data.integral.bit_count,
22077 dest_type->data.integral.is_signed);
22078 }
22079 pointee_val->special = ConstValSpecialStatic;
22080 return ir_const_bool(ira, instruction->base.scope, instruction->base.source_node, result_bool);
22081 }
22082
22083 return ir_build_overflow_op_gen(ira, instruction->base.scope, instruction->base.source_node, instruction->op,
22084 casted_op1, casted_op2, casted_result_ptr, dest_type);
22085}
22086
22087static void ir_eval_mul_add(IrAnalyze *ira, ZigType *float_type,
22088 ZigValue *op1, ZigValue *op2, ZigValue *op3, ZigValue *out_val) {
22089 if (float_type->id == ZigTypeIdComptimeFloat) {
22090 f128M_mulAdd(&out_val->data.x_bigfloat.value, &op1->data.x_bigfloat.value, &op2->data.x_bigfloat.value,
22091 &op3->data.x_bigfloat.value);
22092 } else if (float_type->id == ZigTypeIdFloat) {
22093 switch (float_type->data.floating.bit_count) {
22094 case 16:
22095 out_val->data.x_f16 = f16_mulAdd(op1->data.x_f16, op2->data.x_f16, op3->data.x_f16);
22096 break;
22097 case 32:
22098 out_val->data.x_f32 = fmaf(op1->data.x_f32, op2->data.x_f32, op3->data.x_f32);
22099 break;
22100 case 64:
22101 out_val->data.x_f64 = fma(op1->data.x_f64, op2->data.x_f64, op3->data.x_f64);
22102 break;
22103 case 80:
22104 zig_panic("compiler bug: TODO: implement 'mulAdd' for type 'f80'. See https://github.com/ziglang/zig/issues/4026");
22105 case 128:
22106 f128M_mulAdd(&op1->data.x_f128, &op2->data.x_f128, &op3->data.x_f128, &out_val->data.x_f128);
22107 break;
22108 default:
22109 zig_unreachable();
22110 }
22111 } else {
22112 zig_unreachable();
22113 }
22114}
22115
22116static Stage1AirInst *ir_analyze_instruction_mul_add(IrAnalyze *ira, Stage1ZirInstMulAdd *instruction) {
22117 Stage1AirInst *type_value = instruction->type_value->child;
22118 if (type_is_invalid(type_value->value->type))
22119 return ira->codegen->invalid_inst_gen;
22120
22121 ZigType *expr_type = ir_resolve_type(ira, type_value);
22122 if (type_is_invalid(expr_type))
22123 return ira->codegen->invalid_inst_gen;
22124
22125 // Only allow float types, and vectors of floats.
22126 ZigType *float_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type;
22127 if (float_type->id != ZigTypeIdFloat) {
22128 ir_add_error(ira, type_value,
22129 buf_sprintf("expected float or vector of float type, found '%s'", buf_ptr(&float_type->name)));
22130 return ira->codegen->invalid_inst_gen;
22131 }
22132
22133 Stage1AirInst *op1 = instruction->op1->child;
22134 if (type_is_invalid(op1->value->type))
22135 return ira->codegen->invalid_inst_gen;
22136
22137 Stage1AirInst *casted_op1 = ir_implicit_cast(ira, op1, expr_type);
22138 if (type_is_invalid(casted_op1->value->type))
22139 return ira->codegen->invalid_inst_gen;
22140
22141 Stage1AirInst *op2 = instruction->op2->child;
22142 if (type_is_invalid(op2->value->type))
22143 return ira->codegen->invalid_inst_gen;
22144
22145 Stage1AirInst *casted_op2 = ir_implicit_cast(ira, op2, expr_type);
22146 if (type_is_invalid(casted_op2->value->type))
22147 return ira->codegen->invalid_inst_gen;
22148
22149 Stage1AirInst *op3 = instruction->op3->child;
22150 if (type_is_invalid(op3->value->type))
22151 return ira->codegen->invalid_inst_gen;
22152
22153 Stage1AirInst *casted_op3 = ir_implicit_cast(ira, op3, expr_type);
22154 if (type_is_invalid(casted_op3->value->type))
22155 return ira->codegen->invalid_inst_gen;
22156
22157 if (instr_is_comptime(casted_op1) &&
22158 instr_is_comptime(casted_op2) &&
22159 instr_is_comptime(casted_op3)) {
22160 ZigValue *op1_const = ir_resolve_const(ira, casted_op1, UndefBad);
22161 if (!op1_const)
22162 return ira->codegen->invalid_inst_gen;
22163 ZigValue *op2_const = ir_resolve_const(ira, casted_op2, UndefBad);
22164 if (!op2_const)
22165 return ira->codegen->invalid_inst_gen;
22166 ZigValue *op3_const = ir_resolve_const(ira, casted_op3, UndefBad);
22167 if (!op3_const)
22168 return ira->codegen->invalid_inst_gen;
22169
22170 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, expr_type);
22171 ZigValue *out_val = result->value;
22172
22173 if (expr_type->id == ZigTypeIdVector) {
22174 expand_undef_array(ira->codegen, op1_const);
22175 expand_undef_array(ira->codegen, op2_const);
22176 expand_undef_array(ira->codegen, op3_const);
22177 out_val->special = ConstValSpecialUndef;
22178 expand_undef_array(ira->codegen, out_val);
22179 size_t len = expr_type->data.vector.len;
22180 for (size_t i = 0; i < len; i += 1) {
22181 ZigValue *float_operand_op1 = &op1_const->data.x_array.data.s_none.elements[i];
22182 ZigValue *float_operand_op2 = &op2_const->data.x_array.data.s_none.elements[i];
22183 ZigValue *float_operand_op3 = &op3_const->data.x_array.data.s_none.elements[i];
22184 ZigValue *float_out_val = &out_val->data.x_array.data.s_none.elements[i];
22185 assert(float_operand_op1->type == float_type);
22186 assert(float_operand_op2->type == float_type);
22187 assert(float_operand_op3->type == float_type);
22188 assert(float_out_val->type == float_type);
22189 ir_eval_mul_add(ira, float_type,
22190 op1_const, op2_const, op3_const, float_out_val);
22191 float_out_val->type = float_type;
22192 }
22193 out_val->type = expr_type;
22194 out_val->special = ConstValSpecialStatic;
22195 } else {
22196 ir_eval_mul_add(ira, float_type, op1_const, op2_const, op3_const, out_val);
22197 }
22198 return result;
22199 }
22200
22201 return ir_build_mul_add_gen(ira, instruction->base.scope, instruction->base.source_node, casted_op1, casted_op2, casted_op3, expr_type);
22202}
22203
22204static Stage1AirInst *ir_analyze_instruction_test_err(IrAnalyze *ira, Stage1ZirInstTestErr *instruction) {
22205 Stage1AirInst *base_ptr = instruction->base_ptr->child;
22206 if (type_is_invalid(base_ptr->value->type))
22207 return ira->codegen->invalid_inst_gen;
22208
22209 Stage1AirInst *value;
22210 if (instruction->base_ptr_is_payload) {
22211 value = base_ptr;
22212 } else {
22213 value = ir_get_deref(ira, instruction->base.scope, instruction->base.source_node,
22214 base_ptr, nullptr);
22215 }
22216
22217 ZigType *type_entry = value->value->type;
22218 if (type_is_invalid(type_entry))
22219 return ira->codegen->invalid_inst_gen;
22220 if (type_entry->id == ZigTypeIdErrorUnion) {
22221 if (instr_is_comptime(value)) {
22222 ZigValue *err_union_val = ir_resolve_const(ira, value, UndefBad);
22223 if (!err_union_val)
22224 return ira->codegen->invalid_inst_gen;
22225
22226 if (err_union_val->special != ConstValSpecialRuntime) {
22227 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
22228 return ir_const_bool(ira, instruction->base.scope, instruction->base.source_node, (err != nullptr));
22229 }
22230 }
22231
22232 if (instruction->resolve_err_set) {
22233 ZigType *err_set_type = type_entry->data.error_union.err_set_type;
22234 if (!resolve_inferred_error_set(ira->codegen, err_set_type, instruction->base.source_node)) {
22235 return ira->codegen->invalid_inst_gen;
22236 }
22237 if (!type_is_global_error_set(err_set_type) &&
22238 err_set_type->data.error_set.err_count == 0)
22239 {
22240 assert(!err_set_type->data.error_set.incomplete);
22241 return ir_const_bool(ira, instruction->base.scope, instruction->base.source_node, false);
22242 }
22243 }
22244
22245 return ir_build_test_err_gen(ira, instruction->base.scope, instruction->base.source_node, value);
22246 } else if (type_entry->id == ZigTypeIdErrorSet) {
22247 return ir_const_bool(ira, instruction->base.scope, instruction->base.source_node, true);
22248 } else {
22249 return ir_const_bool(ira, instruction->base.scope, instruction->base.source_node, false);
22250 }
22251}
22252
22253static Stage1AirInst *ir_analyze_unwrap_err_code(IrAnalyze *ira, Scope *scope, AstNode *source_node,
22254 Stage1AirInst *base_ptr, bool initializing)
22255{
22256 ZigType *ptr_type = base_ptr->value->type;
22257
22258 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
22259 assert(ptr_type->id == ZigTypeIdPointer);
22260
22261 ZigType *type_entry = ptr_type->data.pointer.child_type;
22262 if (type_is_invalid(type_entry))
22263 return ira->codegen->invalid_inst_gen;
22264
22265 if (type_entry->id != ZigTypeIdErrorUnion) {
22266 ir_add_error(ira, base_ptr,
22267 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
22268 return ira->codegen->invalid_inst_gen;
22269 }
22270
22271 ZigType *err_set_type = type_entry->data.error_union.err_set_type;
22272 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, err_set_type,
22273 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle,
22274 ptr_type->data.pointer.explicit_alignment, 0, 0, false);
22275
22276 if (instr_is_comptime(base_ptr)) {
22277 ZigValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
22278 if (!ptr_val)
22279 return ira->codegen->invalid_inst_gen;
22280 if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar &&
22281 ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr)
22282 {
22283 ZigValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_node);
22284 if (err_union_val == nullptr)
22285 return ira->codegen->invalid_inst_gen;
22286
22287 if (initializing && err_union_val->special == ConstValSpecialUndef) {
22288 ZigValue *vals = ira->codegen->pass1_arena->allocate<ZigValue>(2);
22289 ZigValue *err_set_val = &vals[0];
22290 ZigValue *payload_val = &vals[1];
22291
22292 err_set_val->special = ConstValSpecialUndef;
22293 err_set_val->type = err_set_type;
22294 err_set_val->parent.id = ConstParentIdErrUnionCode;
22295 err_set_val->parent.data.p_err_union_code.err_union_val = err_union_val;
22296
22297 payload_val->special = ConstValSpecialUndef;
22298 payload_val->type = type_entry->data.error_union.payload_type;
22299 payload_val->parent.id = ConstParentIdErrUnionPayload;
22300 payload_val->parent.data.p_err_union_payload.err_union_val = err_union_val;
22301
22302 err_union_val->special = ConstValSpecialStatic;
22303 err_union_val->data.x_err_union.error_set = err_set_val;
22304 err_union_val->data.x_err_union.payload = payload_val;
22305 }
22306 src_assert(err_union_val->special != ConstValSpecialRuntime, source_node);
22307
22308 Stage1AirInst *result;
22309 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
22310 result = ir_build_unwrap_err_code_gen(ira, scope,
22311 source_node, base_ptr, result_type);
22312 result->value->special = ConstValSpecialStatic;
22313 } else {
22314 result = ir_const(ira, scope, source_node, result_type);
22315 }
22316 ZigValue *const_val = result->value;
22317 const_val->data.x_ptr.special = ConstPtrSpecialBaseErrorUnionCode;
22318 const_val->data.x_ptr.data.base_err_union_code.err_union_val = err_union_val;
22319 const_val->data.x_ptr.mut = ptr_val->data.x_ptr.mut;
22320 return result;
22321 }
22322 }
22323
22324 return ir_build_unwrap_err_code_gen(ira, scope, source_node, base_ptr, result_type);
22325}
22326
22327static Stage1AirInst *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, Stage1ZirInstUnwrapErrCode *instruction) {
22328 Stage1AirInst *base_ptr = instruction->err_union_ptr->child;
22329 if (type_is_invalid(base_ptr->value->type))
22330 return ira->codegen->invalid_inst_gen;
22331 return ir_analyze_unwrap_err_code(ira, instruction->base.scope, instruction->base.source_node, base_ptr, false);
22332}
22333
22334static Stage1AirInst *ir_analyze_unwrap_error_payload(IrAnalyze *ira, Scope *scope, AstNode *source_node,
22335 Stage1AirInst *base_ptr, bool safety_check_on, bool initializing)
22336{
22337 ZigType *ptr_type = base_ptr->value->type;
22338
22339 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
22340 assert(ptr_type->id == ZigTypeIdPointer);
22341
22342 ZigType *type_entry = ptr_type->data.pointer.child_type;
22343 if (type_is_invalid(type_entry))
22344 return ira->codegen->invalid_inst_gen;
22345
22346 if (type_entry->id != ZigTypeIdErrorUnion) {
22347 ir_add_error(ira, base_ptr,
22348 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
22349 return ira->codegen->invalid_inst_gen;
22350 }
22351
22352 ZigType *payload_type = type_entry->data.error_union.payload_type;
22353 if (type_is_invalid(payload_type))
22354 return ira->codegen->invalid_inst_gen;
22355
22356 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
22357 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
22358 PtrLenSingle, 0, 0, 0, false);
22359
22360 if (instr_is_comptime(base_ptr)) {
22361 ZigValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
22362 if (!ptr_val)
22363 return ira->codegen->invalid_inst_gen;
22364 if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
22365 ZigValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_node);
22366 if (err_union_val == nullptr)
22367 return ira->codegen->invalid_inst_gen;
22368 if (initializing && err_union_val->special == ConstValSpecialUndef) {
22369 ZigValue *vals = ira->codegen->pass1_arena->allocate<ZigValue>(2);
22370 ZigValue *err_set_val = &vals[0];
22371 ZigValue *payload_val = &vals[1];
22372
22373 err_set_val->special = ConstValSpecialStatic;
22374 err_set_val->type = type_entry->data.error_union.err_set_type;
22375 err_set_val->data.x_err_set = nullptr;
22376
22377 payload_val->special = ConstValSpecialUndef;
22378 payload_val->type = payload_type;
22379
22380 err_union_val->special = ConstValSpecialStatic;
22381 err_union_val->data.x_err_union.error_set = err_set_val;
22382 err_union_val->data.x_err_union.payload = payload_val;
22383 }
22384
22385 if (err_union_val->special != ConstValSpecialRuntime) {
22386 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
22387 if (err != nullptr) {
22388 ir_add_error_node(ira, source_node,
22389 buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
22390 return ira->codegen->invalid_inst_gen;
22391 }
22392
22393 Stage1AirInst *result;
22394 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
22395 result = ir_build_unwrap_err_payload_gen(ira, scope,
22396 source_node, base_ptr, safety_check_on, initializing, result_type);
22397 result->value->special = ConstValSpecialStatic;
22398 } else {
22399 result = ir_const(ira, scope, source_node, result_type);
22400 }
22401 result->value->data.x_ptr.special = ConstPtrSpecialRef;
22402 result->value->data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
22403 result->value->data.x_ptr.mut = ptr_val->data.x_ptr.mut;
22404 return result;
22405 }
22406 }
22407 }
22408
22409 return ir_build_unwrap_err_payload_gen(ira, scope, source_node,
22410 base_ptr, safety_check_on, initializing, result_type);
22411}
22412
22413static Stage1AirInst *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
22414 Stage1ZirInstUnwrapErrPayload *instruction)
22415{
22416 assert(instruction->value->child);
22417 Stage1AirInst *value = instruction->value->child;
22418 if (type_is_invalid(value->value->type))
22419 return ira->codegen->invalid_inst_gen;
22420
22421 return ir_analyze_unwrap_error_payload(ira, instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on, false);
22422}
22423
22424static Stage1AirInst *ir_analyze_instruction_fn_proto(IrAnalyze *ira, Stage1ZirInstFnProto *instruction) {
22425 AstNode *proto_node = instruction->base.source_node;
22426 assert(proto_node->type == NodeTypeFnProto);
22427
22428 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_type);
22429 result->value->special = ConstValSpecialLazy;
22430
22431 LazyValueFnType *lazy_fn_type = heap::c_allocator.create<LazyValueFnType>();
22432 lazy_fn_type->ira = ira; ira_ref(ira);
22433 result->value->data.x_lazy = &lazy_fn_type->base;
22434 lazy_fn_type->base.id = LazyValueIdFnType;
22435
22436 if (proto_node->data.fn_proto.auto_err_set) {
22437 ir_add_error_node(ira, instruction->base.source_node,
22438 buf_sprintf("inferring error set of return type valid only for function definitions"));
22439 return ira->codegen->invalid_inst_gen;
22440 }
22441
22442 lazy_fn_type->cc = cc_from_fn_proto(&proto_node->data.fn_proto);
22443 if (instruction->callconv_value != nullptr) {
22444 ZigType *cc_enum_type = get_builtin_type(ira->codegen, "CallingConvention");
22445
22446 Stage1AirInst *casted_value = ir_implicit_cast(ira, instruction->callconv_value->child, cc_enum_type);
22447 if (type_is_invalid(casted_value->value->type))
22448 return ira->codegen->invalid_inst_gen;
22449
22450 ZigValue *const_value = ir_resolve_const(ira, casted_value, UndefBad);
22451 if (const_value == nullptr)
22452 return ira->codegen->invalid_inst_gen;
22453
22454 lazy_fn_type->cc = (CallingConvention)bigint_as_u32(&const_value->data.x_enum_tag);
22455 }
22456
22457 size_t param_count = proto_node->data.fn_proto.params.length;
22458 lazy_fn_type->proto_node = proto_node;
22459 lazy_fn_type->param_types = heap::c_allocator.allocate<Stage1AirInst *>(param_count);
22460
22461 for (size_t param_index = 0; param_index < param_count; param_index += 1) {
22462 AstNode *param_node = proto_node->data.fn_proto.params.at(param_index);
22463 assert(param_node->type == NodeTypeParamDecl);
22464
22465 bool param_is_var_args = param_node->data.param_decl.is_var_args;
22466 if (param_is_var_args) {
22467 const CallingConvention cc = lazy_fn_type->cc;
22468
22469 if (cc == CallingConventionC) {
22470 break;
22471 } else {
22472 ir_add_error_node(ira, instruction->base.source_node,
22473 buf_sprintf("var args only allowed in functions with C calling convention"));
22474 return ira->codegen->invalid_inst_gen;
22475 }
22476 }
22477
22478 if (instruction->param_types[param_index] == nullptr) {
22479 lazy_fn_type->is_generic = true;
22480 return result;
22481 }
22482
22483 Stage1AirInst *param_type_value = instruction->param_types[param_index]->child;
22484 if (type_is_invalid(param_type_value->value->type))
22485 return ira->codegen->invalid_inst_gen;
22486 if (ir_resolve_const(ira, param_type_value, LazyOk) == nullptr)
22487 return ira->codegen->invalid_inst_gen;
22488 lazy_fn_type->param_types[param_index] = param_type_value;
22489 }
22490
22491 if (instruction->align_value != nullptr) {
22492 lazy_fn_type->align_inst = instruction->align_value->child;
22493 if (ir_resolve_const(ira, lazy_fn_type->align_inst, LazyOk) == nullptr)
22494 return ira->codegen->invalid_inst_gen;
22495 }
22496
22497 lazy_fn_type->return_type = instruction->return_type->child;
22498 if (ir_resolve_const(ira, lazy_fn_type->return_type, LazyOk) == nullptr)
22499 return ira->codegen->invalid_inst_gen;
22500
22501 return result;
22502}
22503
22504static Stage1AirInst *ir_analyze_instruction_test_comptime(IrAnalyze *ira, Stage1ZirInstTestComptime *instruction) {
22505 Stage1AirInst *value = instruction->value->child;
22506 if (type_is_invalid(value->value->type))
22507 return ira->codegen->invalid_inst_gen;
22508
22509 return ir_const_bool(ira, instruction->base.scope, instruction->base.source_node, instr_is_comptime(value));
22510}
22511
22512static Stage1AirInst *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
22513 Stage1ZirInstCheckSwitchProngs *instruction, bool have_underscore_prong)
22514{
22515 Stage1AirInst *target_value = instruction->target_value->child;
22516 ZigType *switch_type = target_value->value->type;
22517 if (type_is_invalid(switch_type))
22518 return ira->codegen->invalid_inst_gen;
22519
22520 ZigValue *original_value = ((Stage1ZirInstSwitchTarget *)(instruction->target_value))->target_value_ptr->child->value;
22521 bool target_is_originally_union = original_value->type->id == ZigTypeIdPointer &&
22522 original_value->type->data.pointer.child_type->id == ZigTypeIdUnion;
22523
22524 if (switch_type->id == ZigTypeIdEnum) {
22525 HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> field_prev_uses = {};
22526 field_prev_uses.init(switch_type->data.enumeration.src_field_count);
22527
22528 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
22529 Stage1ZirInstCheckSwitchProngsRange *range = &instruction->ranges[range_i];
22530
22531 Stage1AirInst *start_value_uncasted = range->start->child;
22532 if (type_is_invalid(start_value_uncasted->value->type))
22533 return ira->codegen->invalid_inst_gen;
22534 Stage1AirInst *start_value = ir_implicit_cast(ira, start_value_uncasted, switch_type);
22535 if (type_is_invalid(start_value->value->type))
22536 return ira->codegen->invalid_inst_gen;
22537
22538 Stage1AirInst *end_value_uncasted = range->end->child;
22539 if (type_is_invalid(end_value_uncasted->value->type))
22540 return ira->codegen->invalid_inst_gen;
22541 Stage1AirInst *end_value = ir_implicit_cast(ira, end_value_uncasted, switch_type);
22542 if (type_is_invalid(end_value->value->type))
22543 return ira->codegen->invalid_inst_gen;
22544
22545 assert(start_value->value->type->id == ZigTypeIdEnum);
22546 BigInt start_index;
22547 bigint_init_bigint(&start_index, &start_value->value->data.x_enum_tag);
22548
22549 assert(end_value->value->type->id == ZigTypeIdEnum);
22550 BigInt end_index;
22551 bigint_init_bigint(&end_index, &end_value->value->data.x_enum_tag);
22552
22553 if (bigint_cmp(&start_index, &end_index) == CmpGT) {
22554 ir_add_error(ira, start_value,
22555 buf_sprintf("range start value is greater than the end value"));
22556 }
22557
22558 BigInt field_index;
22559 bigint_init_bigint(&field_index, &start_index);
22560 for (;;) {
22561 Cmp cmp = bigint_cmp(&field_index, &end_index);
22562 if (cmp == CmpGT) {
22563 break;
22564 }
22565 auto entry = field_prev_uses.put_unique(field_index, start_value->source_node);
22566 if (entry) {
22567 AstNode *prev_node = entry->value;
22568 TypeEnumField *enum_field = find_enum_field_by_tag(switch_type, &field_index);
22569 assert(enum_field != nullptr);
22570 ErrorMsg *msg = ir_add_error(ira, start_value,
22571 buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&switch_type->name),
22572 buf_ptr(enum_field->name)));
22573 add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value here"));
22574 }
22575 bigint_incr(&field_index);
22576 }
22577 }
22578 if (have_underscore_prong) {
22579 if (!switch_type->data.enumeration.non_exhaustive) {
22580 ir_add_error_node(ira, instruction->base.source_node,
22581 buf_sprintf("switch on exhaustive enum has `_` prong"));
22582 } else if (target_is_originally_union) {
22583 ir_add_error_node(ira, instruction->base.source_node,
22584 buf_sprintf("`_` prong not allowed when switching on tagged union"));
22585 }
22586 for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) {
22587 TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i];
22588 if (buf_eql_str(enum_field->name, "_"))
22589 continue;
22590
22591 auto entry = field_prev_uses.maybe_get(enum_field->value);
22592 if (!entry) {
22593 ir_add_error_node(ira, instruction->base.source_node,
22594 buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&switch_type->name),
22595 buf_ptr(enum_field->name)));
22596 }
22597 }
22598 } else if (instruction->else_prong == nullptr) {
22599 if (switch_type->data.enumeration.non_exhaustive && !target_is_originally_union) {
22600 ir_add_error_node(ira, instruction->base.source_node,
22601 buf_sprintf("switch on non-exhaustive enum must include `else` or `_` prong"));
22602 }
22603 for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) {
22604 TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i];
22605
22606 auto entry = field_prev_uses.maybe_get(enum_field->value);
22607 if (!entry) {
22608 ir_add_error_node(ira, instruction->base.source_node,
22609 buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&switch_type->name),
22610 buf_ptr(enum_field->name)));
22611 }
22612 }
22613 } else if(!switch_type->data.enumeration.non_exhaustive && switch_type->data.enumeration.src_field_count == instruction->range_count) {
22614 ir_add_error_node(ira, instruction->else_prong,
22615 buf_sprintf("unreachable else prong, all cases already handled"));
22616 return ira->codegen->invalid_inst_gen;
22617 }
22618 } else if (switch_type->id == ZigTypeIdErrorSet) {
22619 if (!resolve_inferred_error_set(ira->codegen, switch_type, target_value->source_node)) {
22620 return ira->codegen->invalid_inst_gen;
22621 }
22622
22623 size_t field_prev_uses_count = ira->codegen->errors_by_index.length;
22624 AstNode **field_prev_uses = heap::c_allocator.allocate<AstNode *>(field_prev_uses_count);
22625
22626 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
22627 Stage1ZirInstCheckSwitchProngsRange *range = &instruction->ranges[range_i];
22628
22629 Stage1AirInst *start_value_uncasted = range->start->child;
22630 if (type_is_invalid(start_value_uncasted->value->type))
22631 return ira->codegen->invalid_inst_gen;
22632 Stage1AirInst *start_value = ir_implicit_cast(ira, start_value_uncasted, switch_type);
22633 if (type_is_invalid(start_value->value->type))
22634 return ira->codegen->invalid_inst_gen;
22635
22636 Stage1AirInst *end_value_uncasted = range->end->child;
22637 if (type_is_invalid(end_value_uncasted->value->type))
22638 return ira->codegen->invalid_inst_gen;
22639 Stage1AirInst *end_value = ir_implicit_cast(ira, end_value_uncasted, switch_type);
22640 if (type_is_invalid(end_value->value->type))
22641 return ira->codegen->invalid_inst_gen;
22642
22643 src_assert(start_value->value->type->id == ZigTypeIdErrorSet, instruction->base.source_node);
22644 uint32_t start_index = start_value->value->data.x_err_set->value;
22645
22646 src_assert(end_value->value->type->id == ZigTypeIdErrorSet, instruction->base.source_node);
22647 uint32_t end_index = end_value->value->data.x_err_set->value;
22648
22649 if (start_index != end_index) {
22650 ir_add_error(ira, end_value, buf_sprintf("ranges not allowed when switching on errors"));
22651 return ira->codegen->invalid_inst_gen;
22652 }
22653
22654 AstNode *prev_node = field_prev_uses[start_index];
22655 if (prev_node != nullptr) {
22656 Buf *err_name = &ira->codegen->errors_by_index.at(start_index)->name;
22657 ErrorMsg *msg = ir_add_error(ira, start_value,
22658 buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&switch_type->name), buf_ptr(err_name)));
22659 add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value here"));
22660 }
22661 field_prev_uses[start_index] = start_value->source_node;
22662 }
22663 if (instruction->else_prong == nullptr) {
22664 if (type_is_global_error_set(switch_type)) {
22665 ir_add_error_node(ira, instruction->base.source_node,
22666 buf_sprintf("else prong required when switching on type 'anyerror'"));
22667 return ira->codegen->invalid_inst_gen;
22668 } else {
22669 for (uint32_t i = 0; i < switch_type->data.error_set.err_count; i += 1) {
22670 ErrorTableEntry *err_entry = switch_type->data.error_set.errors[i];
22671
22672 AstNode *prev_node = field_prev_uses[err_entry->value];
22673 if (prev_node == nullptr) {
22674 ir_add_error_node(ira, instruction->base.source_node,
22675 buf_sprintf("error.%s not handled in switch", buf_ptr(&err_entry->name)));
22676 }
22677 }
22678 }
22679 }
22680
22681 heap::c_allocator.deallocate(field_prev_uses, field_prev_uses_count);
22682 } else if (switch_type->id == ZigTypeIdInt) {
22683 RangeSet rs = {0};
22684 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
22685 Stage1ZirInstCheckSwitchProngsRange *range = &instruction->ranges[range_i];
22686
22687 Stage1AirInst *start_value = range->start->child;
22688 if (type_is_invalid(start_value->value->type))
22689 return ira->codegen->invalid_inst_gen;
22690 Stage1AirInst *casted_start_value = ir_implicit_cast(ira, start_value, switch_type);
22691 if (type_is_invalid(casted_start_value->value->type))
22692 return ira->codegen->invalid_inst_gen;
22693
22694 Stage1AirInst *end_value = range->end->child;
22695 if (type_is_invalid(end_value->value->type))
22696 return ira->codegen->invalid_inst_gen;
22697 Stage1AirInst *casted_end_value = ir_implicit_cast(ira, end_value, switch_type);
22698 if (type_is_invalid(casted_end_value->value->type))
22699 return ira->codegen->invalid_inst_gen;
22700
22701 ZigValue *start_val = ir_resolve_const(ira, casted_start_value, UndefBad);
22702 if (!start_val)
22703 return ira->codegen->invalid_inst_gen;
22704
22705 ZigValue *end_val = ir_resolve_const(ira, casted_end_value, UndefBad);
22706 if (!end_val)
22707 return ira->codegen->invalid_inst_gen;
22708
22709 assert(start_val->type->id == ZigTypeIdInt || start_val->type->id == ZigTypeIdComptimeInt);
22710 assert(end_val->type->id == ZigTypeIdInt || end_val->type->id == ZigTypeIdComptimeInt);
22711
22712 if (bigint_cmp(&start_val->data.x_bigint, &end_val->data.x_bigint) == CmpGT) {
22713 ir_add_error(ira, start_value,
22714 buf_sprintf("range start value is greater than the end value"));
22715 }
22716
22717 AstNode *prev_node = rangeset_add_range(&rs, &start_val->data.x_bigint, &end_val->data.x_bigint,
22718 start_value->source_node);
22719 if (prev_node != nullptr) {
22720 ErrorMsg *msg = ir_add_error(ira, start_value, buf_sprintf("duplicate switch value"));
22721 add_error_note(ira->codegen, msg, prev_node, buf_sprintf("previous value here"));
22722 return ira->codegen->invalid_inst_gen;
22723 }
22724 }
22725
22726 BigInt min_val;
22727 eval_min_max_value_int(ira->codegen, switch_type, &min_val, false);
22728 BigInt max_val;
22729 eval_min_max_value_int(ira->codegen, switch_type, &max_val, true);
22730 bool handles_all_cases = rangeset_spans(&rs, &min_val, &max_val);
22731 if (!handles_all_cases && instruction->else_prong == nullptr) {
22732 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("switch must handle all possibilities"));
22733 return ira->codegen->invalid_inst_gen;
22734 } else if(handles_all_cases && instruction->else_prong != nullptr) {
22735 ir_add_error_node(ira, instruction->else_prong,
22736 buf_sprintf("unreachable else prong, all cases already handled"));
22737 return ira->codegen->invalid_inst_gen;
22738 }
22739 } else if (switch_type->id == ZigTypeIdBool) {
22740 int seenTrue = 0;
22741 int seenFalse = 0;
22742 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
22743 Stage1ZirInstCheckSwitchProngsRange *range = &instruction->ranges[range_i];
22744
22745 Stage1AirInst *value = range->start->child;
22746
22747 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, switch_type);
22748 if (type_is_invalid(casted_value->value->type))
22749 return ira->codegen->invalid_inst_gen;
22750
22751 ZigValue *const_expr_val = ir_resolve_const(ira, casted_value, UndefBad);
22752 if (!const_expr_val)
22753 return ira->codegen->invalid_inst_gen;
22754
22755 assert(const_expr_val->type->id == ZigTypeIdBool);
22756
22757 if (const_expr_val->data.x_bool == true) {
22758 seenTrue += 1;
22759 } else {
22760 seenFalse += 1;
22761 }
22762
22763 if ((seenTrue > 1) || (seenFalse > 1)) {
22764 ir_add_error(ira, value, buf_sprintf("duplicate switch value"));
22765 return ira->codegen->invalid_inst_gen;
22766 }
22767 }
22768 if (((seenTrue < 1) || (seenFalse < 1)) && instruction->else_prong == nullptr) {
22769 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("switch must handle all possibilities"));
22770 return ira->codegen->invalid_inst_gen;
22771 }
22772
22773 if(seenTrue == 1 && seenFalse == 1 && instruction->else_prong != nullptr) {
22774 ir_add_error_node(ira, instruction->else_prong,
22775 buf_sprintf("unreachable else prong, all cases already handled"));
22776 return ira->codegen->invalid_inst_gen;
22777 }
22778 } else if (instruction->else_prong == nullptr) {
22779 ir_add_error_node(ira, instruction->base.source_node,
22780 buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name)));
22781 return ira->codegen->invalid_inst_gen;
22782 } else if(switch_type->id == ZigTypeIdMetaType) {
22783 HashMap<const ZigType*, Stage1AirInst*, type_ptr_hash, type_ptr_eql> prevs;
22784 // HashMap doubles capacity when reaching 60% capacity,
22785 // because we know the size at init we can avoid reallocation by doubling it here
22786 prevs.init(instruction->range_count * 2);
22787 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
22788 Stage1ZirInstCheckSwitchProngsRange *range = &instruction->ranges[range_i];
22789
22790 Stage1AirInst *value = range->start->child;
22791 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, switch_type);
22792 if (type_is_invalid(casted_value->value->type)) {
22793 prevs.deinit();
22794 return ira->codegen->invalid_inst_gen;
22795 }
22796
22797 ZigValue *const_expr_val = ir_resolve_const(ira, casted_value, UndefBad);
22798 if (!const_expr_val) {
22799 prevs.deinit();
22800 return ira->codegen->invalid_inst_gen;
22801 }
22802
22803 auto entry = prevs.put_unique(const_expr_val->data.x_type, value);
22804 if(entry != nullptr) {
22805 ErrorMsg *msg = ir_add_error(ira, value, buf_sprintf("duplicate switch value"));
22806 add_error_note(ira->codegen, msg, entry->value->source_node, buf_sprintf("previous value here"));
22807 prevs.deinit();
22808 return ira->codegen->invalid_inst_gen;
22809 }
22810 }
22811 prevs.deinit();
22812 }
22813 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
22814}
22815
22816static Stage1AirInst *ir_analyze_instruction_check_statement_is_void(IrAnalyze *ira,
22817 Stage1ZirInstCheckStatementIsVoid *instruction)
22818{
22819 Stage1AirInst *statement_value = instruction->statement_value->child;
22820 ZigType *statement_type = statement_value->value->type;
22821 if (type_is_invalid(statement_type))
22822 return ira->codegen->invalid_inst_gen;
22823
22824 if (statement_type->id != ZigTypeIdVoid && statement_type->id != ZigTypeIdUnreachable) {
22825 if(statement_type->id == ZigTypeIdErrorUnion || statement_type->id == ZigTypeIdErrorSet) {
22826 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("error is ignored. consider using `try`, `catch`, or `if`"));
22827 }else{
22828 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("expression value is ignored"));
22829 }
22830 }
22831
22832 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
22833}
22834
22835static Stage1AirInst *ir_analyze_instruction_panic(IrAnalyze *ira, Stage1ZirInstPanic *instruction) {
22836 Stage1AirInst *msg = instruction->msg->child;
22837 if (type_is_invalid(msg->value->type))
22838 return ir_unreach_error(ira);
22839
22840 if (ir_should_inline(ira->zir, instruction->base.scope)) {
22841 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("encountered @panic at compile-time"));
22842 return ir_unreach_error(ira);
22843 }
22844
22845 ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
22846 true, false, PtrLenUnknown, 0, 0, 0, false);
22847 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);
22848 Stage1AirInst *casted_msg = ir_implicit_cast(ira, msg, str_type);
22849 if (type_is_invalid(casted_msg->value->type))
22850 return ir_unreach_error(ira);
22851
22852 Stage1AirInst *new_instruction = ir_build_panic_gen(ira, instruction->base.scope, instruction->base.source_node, casted_msg);
22853 return ir_finish_anal(ira, new_instruction);
22854}
22855
22856static Stage1AirInst *ir_align_cast(IrAnalyze *ira, Stage1AirInst *target, uint32_t align_bytes, bool safety_check_on) {
22857 Error err;
22858
22859 ZigType *target_type = target->value->type;
22860 assert(!type_is_invalid(target_type));
22861
22862 ZigType *result_type;
22863 uint32_t old_align_bytes;
22864
22865 ZigType *actual_ptr = target_type;
22866 if (actual_ptr->id == ZigTypeIdOptional) {
22867 actual_ptr = actual_ptr->data.maybe.child_type;
22868 } else if (is_slice(actual_ptr)) {
22869 actual_ptr = actual_ptr->data.structure.fields[slice_ptr_index]->type_entry;
22870 }
22871
22872 if (safety_check_on && !type_has_bits(ira->codegen, actual_ptr)) {
22873 ir_add_error(ira, target,
22874 buf_sprintf("cannot adjust alignment of zero sized type '%s'", buf_ptr(&target_type->name)));
22875 return ira->codegen->invalid_inst_gen;
22876 }
22877
22878 if (target_type->id == ZigTypeIdPointer) {
22879 if ((err = resolve_ptr_align(ira, target_type, &old_align_bytes)))
22880 return ira->codegen->invalid_inst_gen;
22881 result_type = adjust_ptr_align(ira->codegen, target_type, align_bytes);
22882 } else if (target_type->id == ZigTypeIdFn) {
22883 FnTypeId fn_type_id = target_type->data.fn.fn_type_id;
22884 old_align_bytes = fn_type_id.alignment;
22885 fn_type_id.alignment = align_bytes;
22886 result_type = get_fn_type(ira->codegen, &fn_type_id);
22887 } else if (target_type->id == ZigTypeIdAnyFrame) {
22888 if (align_bytes >= get_async_frame_align_bytes(ira->codegen)) {
22889 result_type = target_type;
22890 } else {
22891 ir_add_error(ira, target, buf_sprintf("sub-aligned anyframe not allowed"));
22892 return ira->codegen->invalid_inst_gen;
22893 }
22894 } else if (target_type->id == ZigTypeIdOptional &&
22895 target_type->data.maybe.child_type->id == ZigTypeIdPointer)
22896 {
22897 ZigType *ptr_type = target_type->data.maybe.child_type;
22898 if ((err = resolve_ptr_align(ira, ptr_type, &old_align_bytes)))
22899 return ira->codegen->invalid_inst_gen;
22900 ZigType *better_ptr_type = adjust_ptr_align(ira->codegen, ptr_type, align_bytes);
22901
22902 result_type = get_optional_type(ira->codegen, better_ptr_type);
22903 } else if (target_type->id == ZigTypeIdOptional &&
22904 target_type->data.maybe.child_type->id == ZigTypeIdFn)
22905 {
22906 FnTypeId fn_type_id = target_type->data.maybe.child_type->data.fn.fn_type_id;
22907 old_align_bytes = fn_type_id.alignment;
22908 fn_type_id.alignment = align_bytes;
22909 ZigType *fn_type = get_fn_type(ira->codegen, &fn_type_id);
22910 result_type = get_optional_type(ira->codegen, fn_type);
22911 } else if (is_slice(target_type)) {
22912 ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index]->type_entry;
22913 if ((err = resolve_ptr_align(ira, slice_ptr_type, &old_align_bytes)))
22914 return ira->codegen->invalid_inst_gen;
22915 ZigType *result_ptr_type = adjust_ptr_align(ira->codegen, slice_ptr_type, align_bytes);
22916 result_type = get_slice_type(ira->codegen, result_ptr_type);
22917 } else {
22918 ir_add_error(ira, target,
22919 buf_sprintf("expected pointer or slice, found '%s'", buf_ptr(&target_type->name)));
22920 return ira->codegen->invalid_inst_gen;
22921 }
22922
22923 if (instr_is_comptime(target)) {
22924 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
22925 if (!val)
22926 return ira->codegen->invalid_inst_gen;
22927
22928 if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
22929 val->data.x_ptr.data.hard_coded_addr.addr % align_bytes != 0)
22930 {
22931 ir_add_error(ira, target,
22932 buf_sprintf("pointer address 0x%" ZIG_PRI_x64 " is not aligned to %" PRIu32 " bytes",
22933 val->data.x_ptr.data.hard_coded_addr.addr, align_bytes));
22934 return ira->codegen->invalid_inst_gen;
22935 }
22936
22937 Stage1AirInst *result = ir_const(ira, target->scope, target->source_node, result_type);
22938 copy_const_val(ira->codegen, result->value, val);
22939 result->value->type = result_type;
22940 return result;
22941 }
22942
22943 if (safety_check_on && align_bytes > old_align_bytes && align_bytes != 1) {
22944 return ir_build_align_cast_gen(ira, target->scope, target->source_node, target, result_type);
22945 } else {
22946 return ir_build_cast(ira, target->scope, target->source_node, result_type, target, CastOpNoop);
22947 }
22948}
22949
22950static Stage1AirInst *ir_analyze_ptr_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node,
22951 Stage1AirInst *ptr, AstNode *ptr_src, ZigType *dest_type, AstNode *dest_type_src,
22952 bool safety_check_on, bool keep_bigger_alignment)
22953{
22954 Error err;
22955
22956 ZigType *src_type = ptr->value->type;
22957 assert(!type_is_invalid(src_type));
22958
22959 if (src_type == dest_type) {
22960 return ptr;
22961 }
22962
22963 // We have a check for zero bits later so we use get_src_ptr_type to
22964 // validate src_type and dest_type.
22965
22966 ZigType *if_slice_ptr_type;
22967 if (is_slice(src_type)) {
22968 TypeStructField *ptr_field = src_type->data.structure.fields[slice_ptr_index];
22969 if_slice_ptr_type = resolve_struct_field_type(ira->codegen, ptr_field);
22970 } else {
22971 if_slice_ptr_type = src_type;
22972
22973 ZigType *src_ptr_type = get_src_ptr_type(src_type);
22974 if (src_ptr_type == nullptr) {
22975 ir_add_error_node(ira, ptr_src,
22976 buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
22977 return ira->codegen->invalid_inst_gen;
22978 }
22979 }
22980
22981 ZigType *dest_ptr_type = get_src_ptr_type(dest_type);
22982 if (dest_ptr_type == nullptr) {
22983 ir_add_error_node(ira, dest_type_src,
22984 buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
22985 return ira->codegen->invalid_inst_gen;
22986 }
22987
22988 if (get_ptr_const(ira->codegen, src_type) && !get_ptr_const(ira->codegen, dest_type)) {
22989 ir_add_error_node(ira, source_node, buf_sprintf("cast discards const qualifier"));
22990 return ira->codegen->invalid_inst_gen;
22991 }
22992 uint32_t dest_align_bytes;
22993 if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes)))
22994 return ira->codegen->invalid_inst_gen;
22995
22996 uint32_t src_align_bytes = 0;
22997 if (keep_bigger_alignment || dest_align_bytes != 1) {
22998 if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes)))
22999 return ira->codegen->invalid_inst_gen;
23000 }
23001
23002 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
23003 return ira->codegen->invalid_inst_gen;
23004
23005 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusZeroBitsKnown)))
23006 return ira->codegen->invalid_inst_gen;
23007
23008 if (safety_check_on &&
23009 type_has_bits(ira->codegen, dest_type) &&
23010 !type_has_bits(ira->codegen, if_slice_ptr_type))
23011 {
23012 ErrorMsg *msg = ir_add_error_node(ira, source_node,
23013 buf_sprintf("'%s' and '%s' do not have the same in-memory representation",
23014 buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
23015 add_error_note(ira->codegen, msg, ptr_src,
23016 buf_sprintf("'%s' has no in-memory bits", buf_ptr(&src_type->name)));
23017 add_error_note(ira->codegen, msg, dest_type_src,
23018 buf_sprintf("'%s' has in-memory bits", buf_ptr(&dest_type->name)));
23019 return ira->codegen->invalid_inst_gen;
23020 }
23021
23022 // For slices, follow the `ptr` field.
23023 if (is_slice(src_type)) {
23024 TypeStructField *ptr_field = src_type->data.structure.fields[slice_ptr_index];
23025 Stage1AirInst *ptr_ref = ir_get_ref(ira, scope, source_node, ptr, true, false);
23026 Stage1AirInst *ptr_ptr = ir_analyze_struct_field_ptr(ira, scope, source_node, ptr_field, ptr_ref, src_type, false);
23027 ptr = ir_get_deref(ira, scope, source_node, ptr_ptr, nullptr);
23028 }
23029
23030 if (instr_is_comptime(ptr)) {
23031 bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type);
23032 UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad;
23033 ZigValue *val = ir_resolve_const(ira, ptr, is_undef_allowed);
23034 if (val == nullptr)
23035 return ira->codegen->invalid_inst_gen;
23036
23037 if (value_is_comptime(val) && val->special != ConstValSpecialUndef) {
23038 bool is_addr_zero = val->data.x_ptr.special == ConstPtrSpecialNull ||
23039 (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
23040 val->data.x_ptr.data.hard_coded_addr.addr == 0);
23041 if (is_addr_zero && !dest_allows_addr_zero) {
23042 ir_add_error_node(ira, source_node,
23043 buf_sprintf("null pointer casted to type '%s'", buf_ptr(&dest_type->name)));
23044 return ira->codegen->invalid_inst_gen;
23045 }
23046 }
23047
23048 Stage1AirInst *result;
23049 if (val->data.x_ptr.mut == ConstPtrMutInfer) {
23050 result = ir_build_ptr_cast_gen(ira, scope, source_node, dest_type, ptr, safety_check_on);
23051 } else {
23052 result = ir_const(ira, scope, source_node, dest_type);
23053 }
23054 InferredStructField *isf = (val->type->id == ZigTypeIdPointer) ?
23055 val->type->data.pointer.inferred_struct_field : nullptr;
23056 if (isf == nullptr) {
23057 copy_const_val(ira->codegen, result->value, val);
23058 } else {
23059 // The destination value should have x_ptr struct pointing to underlying struct value
23060 result->value->data.x_ptr.mut = val->data.x_ptr.mut;
23061 TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
23062 assert(field != nullptr);
23063 if (field->is_comptime) {
23064 result->value->data.x_ptr.special = ConstPtrSpecialRef;
23065 result->value->data.x_ptr.data.ref.pointee = field->init_val;
23066 } else {
23067 assert(val->data.x_ptr.special == ConstPtrSpecialRef);
23068 result->value->data.x_ptr.special = ConstPtrSpecialBaseStruct;
23069 result->value->data.x_ptr.data.base_struct.struct_val = val->data.x_ptr.data.ref.pointee;
23070 result->value->data.x_ptr.data.base_struct.field_index = field->src_index;
23071 }
23072 result->value->special = ConstValSpecialStatic;
23073 }
23074 result->value->type = dest_type;
23075
23076 // Keep the bigger alignment, it can only help- unless the target is zero bits.
23077 if (keep_bigger_alignment && src_align_bytes > dest_align_bytes && type_has_bits(ira->codegen, dest_type)) {
23078 result = ir_align_cast(ira, result, src_align_bytes, false);
23079 }
23080
23081 return result;
23082 }
23083
23084 if (src_align_bytes != 0 && dest_align_bytes > src_align_bytes) {
23085 ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("cast increases pointer alignment"));
23086 add_error_note(ira->codegen, msg, ptr_src,
23087 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_type->name), src_align_bytes));
23088 add_error_note(ira->codegen, msg, dest_type_src,
23089 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&dest_type->name), dest_align_bytes));
23090 return ira->codegen->invalid_inst_gen;
23091 }
23092
23093 Stage1AirInst *casted_ptr = ir_build_ptr_cast_gen(ira, scope, source_node, dest_type, ptr, safety_check_on);
23094
23095 // Keep the bigger alignment, it can only help- unless the target is zero bits.
23096 Stage1AirInst *result;
23097 if (keep_bigger_alignment && src_align_bytes > dest_align_bytes && type_has_bits(ira->codegen, dest_type)) {
23098 result = ir_align_cast(ira, casted_ptr, src_align_bytes, false);
23099 if (type_is_invalid(result->value->type))
23100 return ira->codegen->invalid_inst_gen;
23101 } else {
23102 result = casted_ptr;
23103 }
23104 return result;
23105}
23106
23107static Stage1AirInst *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, Stage1ZirInstPtrCast *instruction) {
23108 Stage1AirInst *dest_type_value = instruction->dest_type->child;
23109 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
23110 if (type_is_invalid(dest_type))
23111 return ira->codegen->invalid_inst_gen;
23112
23113 Stage1AirInst *ptr = instruction->ptr->child;
23114 ZigType *src_type = ptr->value->type;
23115 if (type_is_invalid(src_type))
23116 return ira->codegen->invalid_inst_gen;
23117
23118 // This logic is not quite right; this is just to get stage1 to accept valid code
23119 // we use in the self-hosted compiler.
23120 if (is_slice(dest_type) && is_slice(src_type)) {
23121 return ir_analyze_bit_cast(ira, instruction->base.scope, instruction->base.source_node, ptr, dest_type);
23122 }
23123
23124 bool keep_bigger_alignment = true;
23125 return ir_analyze_ptr_cast(ira, instruction->base.scope, instruction->base.source_node, ptr,
23126 instruction->ptr->source_node, dest_type, dest_type_value->source_node,
23127 instruction->safety_check_on, keep_bigger_alignment);
23128}
23129
23130static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ZigValue *val, size_t len) {
23131 size_t buf_i = 0;
23132 // TODO optimize the buf case
23133 expand_undef_array(codegen, val);
23134 for (size_t elem_i = 0; elem_i < val->type->data.array.len; elem_i += 1) {
23135 ZigValue *elem = &val->data.x_array.data.s_none.elements[elem_i];
23136 buf_write_value_bytes(codegen, &buf[buf_i], elem);
23137 buf_i += type_size(codegen, elem->type);
23138 }
23139 if (val->type->id == ZigTypeIdArray && val->type->data.array.sentinel != nullptr) {
23140 buf_write_value_bytes(codegen, &buf[buf_i], val->type->data.array.sentinel);
23141 }
23142}
23143
23144static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val) {
23145 if (val->special == ConstValSpecialUndef) {
23146 expand_undef_struct(codegen, val);
23147 val->special = ConstValSpecialStatic;
23148 }
23149 assert(val->special == ConstValSpecialStatic);
23150 switch (val->type->id) {
23151 case ZigTypeIdInvalid:
23152 case ZigTypeIdMetaType:
23153 case ZigTypeIdOpaque:
23154 case ZigTypeIdBoundFn:
23155 case ZigTypeIdUnreachable:
23156 case ZigTypeIdComptimeFloat:
23157 case ZigTypeIdComptimeInt:
23158 case ZigTypeIdEnumLiteral:
23159 case ZigTypeIdUndefined:
23160 case ZigTypeIdNull:
23161 case ZigTypeIdErrorUnion:
23162 case ZigTypeIdErrorSet:
23163 zig_unreachable();
23164 case ZigTypeIdVoid:
23165 return;
23166 case ZigTypeIdBool:
23167 buf[0] = val->data.x_bool ? 1 : 0;
23168 return;
23169 case ZigTypeIdInt:
23170 bigint_write_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
23171 codegen->is_big_endian);
23172 return;
23173 case ZigTypeIdEnum:
23174 bigint_write_twos_complement(&val->data.x_enum_tag, buf,
23175 val->type->data.enumeration.tag_int_type->data.integral.bit_count,
23176 codegen->is_big_endian);
23177 return;
23178 case ZigTypeIdFloat:
23179 float_write_ieee597(val, buf, codegen->is_big_endian);
23180 return;
23181 case ZigTypeIdPointer:
23182 if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
23183 BigInt bn;
23184 bigint_init_unsigned(&bn, val->data.x_ptr.data.hard_coded_addr.addr);
23185 bigint_write_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, codegen->is_big_endian);
23186 return;
23187 } else {
23188 zig_unreachable();
23189 }
23190 case ZigTypeIdArray:
23191 return buf_write_value_bytes_array(codegen, buf, val, val->type->data.array.len);
23192 case ZigTypeIdVector:
23193 return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len);
23194 case ZigTypeIdStruct:
23195 switch (val->type->data.structure.layout) {
23196 case ContainerLayoutAuto:
23197 zig_unreachable();
23198 case ContainerLayoutExtern: {
23199 size_t src_field_count = val->type->data.structure.src_field_count;
23200 for (size_t field_i = 0; field_i < src_field_count; field_i += 1) {
23201 TypeStructField *struct_field = val->type->data.structure.fields[field_i];
23202 if (struct_field->gen_index == SIZE_MAX || struct_field->is_comptime)
23203 continue;
23204 ZigValue *field_val = val->data.x_struct.fields[field_i];
23205 size_t offset = struct_field->offset;
23206 buf_write_value_bytes(codegen, buf + offset, field_val);
23207 }
23208 return;
23209 }
23210 case ContainerLayoutPacked: {
23211 size_t src_field_count = val->type->data.structure.src_field_count;
23212 size_t gen_field_count = val->type->data.structure.gen_field_count;
23213 size_t gen_i = 0;
23214 size_t src_i = 0;
23215 size_t offset = 0;
23216 bool is_big_endian = codegen->is_big_endian;
23217 uint8_t child_buf_prealloc[16];
23218 size_t child_buf_len = 16;
23219 uint8_t *child_buf = child_buf_prealloc;
23220 while (gen_i < gen_field_count) {
23221 size_t big_int_byte_count = val->type->data.structure.host_int_bytes[gen_i];
23222 if (big_int_byte_count > child_buf_len) {
23223 child_buf = heap::c_allocator.allocate_nonzero<uint8_t>(big_int_byte_count);
23224 child_buf_len = big_int_byte_count;
23225 }
23226 BigInt big_int;
23227 bigint_init_unsigned(&big_int, 0);
23228 size_t used_bits = 0;
23229 while (src_i < src_field_count) {
23230 TypeStructField *field = val->type->data.structure.fields[src_i];
23231 if (field->is_comptime) {
23232 src_i += 1;
23233 continue;
23234 }
23235 assert(field->gen_index != SIZE_MAX);
23236 if (field->gen_index != gen_i)
23237 break;
23238 uint32_t packed_bits_size = type_size_bits(codegen, field->type_entry);
23239 buf_write_value_bytes(codegen, child_buf, val->data.x_struct.fields[src_i]);
23240 BigInt child_val;
23241 bigint_read_twos_complement(&child_val, child_buf, packed_bits_size, is_big_endian,
23242 false);
23243 if (is_big_endian) {
23244 BigInt shift_amt;
23245 bigint_init_unsigned(&shift_amt, packed_bits_size);
23246 BigInt shifted;
23247 bigint_shl(&shifted, &big_int, &shift_amt);
23248 bigint_or(&big_int, &shifted, &child_val);
23249 } else {
23250 BigInt shift_amt;
23251 bigint_init_unsigned(&shift_amt, used_bits);
23252 BigInt child_val_shifted;
23253 bigint_shl(&child_val_shifted, &child_val, &shift_amt);
23254 BigInt tmp;
23255 bigint_or(&tmp, &big_int, &child_val_shifted);
23256 big_int = tmp;
23257 used_bits += packed_bits_size;
23258 }
23259 src_i += 1;
23260 }
23261 bigint_write_twos_complement(&big_int, buf + offset, big_int_byte_count * 8, is_big_endian);
23262 offset += big_int_byte_count;
23263 gen_i += 1;
23264 }
23265 return;
23266 }
23267 }
23268 zig_unreachable();
23269 case ZigTypeIdOptional:
23270 zig_panic("TODO buf_write_value_bytes maybe type");
23271 case ZigTypeIdFn:
23272 zig_panic("TODO buf_write_value_bytes fn type");
23273 case ZigTypeIdUnion:
23274 zig_panic("TODO buf_write_value_bytes union type");
23275 case ZigTypeIdFnFrame:
23276 zig_panic("TODO buf_write_value_bytes async fn frame type");
23277 case ZigTypeIdAnyFrame:
23278 zig_panic("TODO buf_write_value_bytes anyframe type");
23279 }
23280 zig_unreachable();
23281}
23282
23283static Error buf_read_value_bytes_array(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf,
23284 ZigValue *val, ZigType *elem_type, size_t len)
23285{
23286 Error err;
23287 uint64_t elem_size = type_size(codegen, elem_type);
23288
23289 switch (val->data.x_array.special) {
23290 case ConstArraySpecialNone:
23291 val->data.x_array.data.s_none.elements = codegen->pass1_arena->allocate<ZigValue>(len);
23292 for (size_t i = 0; i < len; i++) {
23293 ZigValue *elem = &val->data.x_array.data.s_none.elements[i];
23294 elem->special = ConstValSpecialStatic;
23295 elem->type = elem_type;
23296 if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem)))
23297 return err;
23298 }
23299 return ErrorNone;
23300 case ConstArraySpecialUndef:
23301 zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type");
23302 case ConstArraySpecialBuf:
23303 zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type");
23304 }
23305 zig_unreachable();
23306}
23307
23308static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ZigValue *val) {
23309 Error err;
23310 src_assert(val->special == ConstValSpecialStatic, source_node);
23311 switch (val->type->id) {
23312 case ZigTypeIdInvalid:
23313 case ZigTypeIdMetaType:
23314 case ZigTypeIdOpaque:
23315 case ZigTypeIdBoundFn:
23316 case ZigTypeIdUnreachable:
23317 case ZigTypeIdComptimeFloat:
23318 case ZigTypeIdComptimeInt:
23319 case ZigTypeIdEnumLiteral:
23320 case ZigTypeIdUndefined:
23321 case ZigTypeIdNull:
23322 zig_unreachable();
23323 case ZigTypeIdVoid:
23324 return ErrorNone;
23325 case ZigTypeIdBool:
23326 val->data.x_bool = (buf[0] != 0);
23327 return ErrorNone;
23328 case ZigTypeIdInt:
23329 bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
23330 codegen->is_big_endian, val->type->data.integral.is_signed);
23331 return ErrorNone;
23332 case ZigTypeIdFloat:
23333 float_read_ieee597(val, buf, codegen->is_big_endian);
23334 return ErrorNone;
23335 case ZigTypeIdPointer:
23336 {
23337 val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
23338 BigInt bn;
23339 bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,
23340 codegen->is_big_endian, false);
23341 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_usize(&bn);
23342 return ErrorNone;
23343 }
23344 case ZigTypeIdArray:
23345 return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.array.child_type,
23346 val->type->data.array.len);
23347 case ZigTypeIdVector:
23348 return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.vector.elem_type,
23349 val->type->data.vector.len);
23350 case ZigTypeIdEnum: {
23351 ZigType *tag_int_type = val->type->data.enumeration.tag_int_type;
23352 src_assert(tag_int_type->id == ZigTypeIdInt, source_node);
23353 bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count,
23354 codegen->is_big_endian, tag_int_type->data.integral.is_signed);
23355 return ErrorNone;
23356 } case ZigTypeIdStruct:
23357 switch (val->type->data.structure.layout) {
23358 case ContainerLayoutAuto: {
23359 switch(val->type->data.structure.special){
23360 case StructSpecialNone:
23361 case StructSpecialInferredTuple:
23362 case StructSpecialInferredStruct: {
23363 ErrorMsg *msg = opt_ir_add_error_node(ira, codegen, source_node,
23364 buf_sprintf("non-extern, non-packed struct '%s' cannot have its bytes reinterpreted",
23365 buf_ptr(&val->type->name)));
23366 add_error_note(codegen, msg, val->type->data.structure.decl_node,
23367 buf_sprintf("declared here"));
23368 break;
23369 }
23370 case StructSpecialSlice: {
23371 opt_ir_add_error_node(ira, codegen, source_node,
23372 buf_sprintf("slice '%s' cannot have its bytes reinterpreted",
23373 buf_ptr(&val->type->name)));
23374 break;
23375 }
23376 }
23377 return ErrorSemanticAnalyzeFail;
23378 }
23379 case ContainerLayoutExtern: {
23380 size_t src_field_count = val->type->data.structure.src_field_count;
23381 val->data.x_struct.fields = alloc_const_vals_ptrs(codegen, src_field_count);
23382 for (size_t field_i = 0; field_i < src_field_count; field_i += 1) {
23383 TypeStructField *struct_field = val->type->data.structure.fields[field_i];
23384 if (struct_field->is_comptime)
23385 continue;
23386 ZigValue *field_val = val->data.x_struct.fields[field_i];
23387 field_val->special = ConstValSpecialStatic;
23388 field_val->type = struct_field->type_entry;
23389 if (struct_field->gen_index == SIZE_MAX)
23390 continue;
23391 size_t offset = struct_field->offset;
23392 uint8_t *new_buf = buf + offset;
23393 if ((err = buf_read_value_bytes(ira, codegen, source_node, new_buf, field_val)))
23394 return err;
23395 }
23396 return ErrorNone;
23397 }
23398 case ContainerLayoutPacked: {
23399 size_t src_field_count = val->type->data.structure.src_field_count;
23400 val->data.x_struct.fields = alloc_const_vals_ptrs(codegen, src_field_count);
23401 size_t gen_field_count = val->type->data.structure.gen_field_count;
23402 size_t gen_i = 0;
23403 size_t src_i = 0;
23404 size_t offset = 0;
23405 bool is_big_endian = codegen->is_big_endian;
23406 uint8_t child_buf_prealloc[16];
23407 size_t child_buf_len = 16;
23408 uint8_t *child_buf = child_buf_prealloc;
23409 while (gen_i < gen_field_count) {
23410 size_t big_int_byte_count = val->type->data.structure.host_int_bytes[gen_i];
23411 if (big_int_byte_count > child_buf_len) {
23412 child_buf = heap::c_allocator.allocate_nonzero<uint8_t>(big_int_byte_count);
23413 child_buf_len = big_int_byte_count;
23414 }
23415 BigInt big_int;
23416 bigint_read_twos_complement(&big_int, buf + offset, big_int_byte_count * 8, is_big_endian, false);
23417 uint64_t bit_offset = 0;
23418 while (src_i < src_field_count) {
23419 TypeStructField *field = val->type->data.structure.fields[src_i];
23420 if (field->is_comptime) {
23421 src_i += 1;
23422 continue;
23423 }
23424 src_assert(field->gen_index != SIZE_MAX, source_node);
23425 if (field->gen_index != gen_i)
23426 break;
23427 ZigValue *field_val = val->data.x_struct.fields[src_i];
23428 field_val->special = ConstValSpecialStatic;
23429 field_val->type = field->type_entry;
23430 uint32_t packed_bits_size = type_size_bits(codegen, field->type_entry);
23431
23432 BigInt child_val;
23433 if (is_big_endian) {
23434 BigInt packed_bits_size_bi;
23435 bigint_init_unsigned(&packed_bits_size_bi, big_int_byte_count * 8 - packed_bits_size - bit_offset);
23436 BigInt tmp;
23437 bigint_shr(&tmp, &big_int, &packed_bits_size_bi);
23438 bigint_truncate(&child_val, &tmp, packed_bits_size, false);
23439 } else {
23440 BigInt packed_bits_size_bi;
23441 bigint_init_unsigned(&packed_bits_size_bi, packed_bits_size);
23442 bigint_truncate(&child_val, &big_int, packed_bits_size, false);
23443 BigInt tmp;
23444 bigint_shr(&tmp, &big_int, &packed_bits_size_bi);
23445 big_int = tmp;
23446 }
23447
23448 bigint_write_twos_complement(&child_val, child_buf, packed_bits_size, is_big_endian);
23449 if ((err = buf_read_value_bytes(ira, codegen, source_node, child_buf, field_val))) {
23450 return err;
23451 }
23452
23453 bit_offset += packed_bits_size;
23454 src_i += 1;
23455 }
23456 offset += big_int_byte_count;
23457 gen_i += 1;
23458 }
23459 return ErrorNone;
23460 }
23461 }
23462 zig_unreachable();
23463 case ZigTypeIdOptional:
23464 zig_panic("TODO buf_read_value_bytes maybe type");
23465 case ZigTypeIdErrorUnion:
23466 zig_panic("TODO buf_read_value_bytes error union");
23467 case ZigTypeIdErrorSet:
23468 zig_panic("TODO buf_read_value_bytes pure error type");
23469 case ZigTypeIdFn:
23470 zig_panic("TODO buf_read_value_bytes fn type");
23471 case ZigTypeIdUnion:
23472 zig_panic("TODO buf_read_value_bytes union type");
23473 case ZigTypeIdFnFrame:
23474 zig_panic("TODO buf_read_value_bytes async fn frame type");
23475 case ZigTypeIdAnyFrame:
23476 zig_panic("TODO buf_read_value_bytes anyframe type");
23477 }
23478 zig_unreachable();
23479}
23480
23481static Stage1AirInst *ir_analyze_bit_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value,
23482 ZigType *dest_type)
23483{
23484 Error err;
23485
23486 ZigType *src_type = value->value->type;
23487 src_assert(type_can_bit_cast(src_type), source_node);
23488 src_assert(type_can_bit_cast(dest_type), source_node);
23489
23490 if (dest_type->id == ZigTypeIdEnum) {
23491 ErrorMsg *msg = ir_add_error_node(ira, source_node,
23492 buf_sprintf("cannot cast a value of type '%s'", buf_ptr(&dest_type->name)));
23493 add_error_note(ira->codegen, msg, source_node,
23494 buf_sprintf("use @intToEnum for type coercion"));
23495 return ira->codegen->invalid_inst_gen;
23496 }
23497
23498 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
23499 return ira->codegen->invalid_inst_gen;
23500
23501 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
23502 return ira->codegen->invalid_inst_gen;
23503
23504 const bool src_is_ptr = handle_is_ptr(ira->codegen, src_type);
23505 const bool dest_is_ptr = handle_is_ptr(ira->codegen, dest_type);
23506
23507 const uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
23508 const uint64_t src_size_bytes = type_size(ira->codegen, src_type);
23509 if (dest_size_bytes != src_size_bytes) {
23510 ir_add_error_node(ira, source_node,
23511 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
23512 buf_ptr(&dest_type->name), dest_size_bytes,
23513 buf_ptr(&src_type->name), src_size_bytes));
23514 return ira->codegen->invalid_inst_gen;
23515 }
23516
23517 const uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
23518 const uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
23519 if (dest_size_bits != src_size_bits) {
23520 ir_add_error_node(ira, source_node,
23521 buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",
23522 buf_ptr(&dest_type->name), dest_size_bits,
23523 buf_ptr(&src_type->name), src_size_bits));
23524 return ira->codegen->invalid_inst_gen;
23525 }
23526
23527 if (instr_is_comptime(value)) {
23528 ZigValue *val = ir_resolve_const(ira, value, UndefBad);
23529 if (!val)
23530 return ira->codegen->invalid_inst_gen;
23531
23532 Stage1AirInst *result = ir_const(ira, scope, source_node, dest_type);
23533 uint8_t *buf = heap::c_allocator.allocate_nonzero<uint8_t>(src_size_bytes);
23534 buf_write_value_bytes(ira->codegen, buf, val);
23535 if ((err = buf_read_value_bytes(ira, ira->codegen, source_node, buf, result->value)))
23536 return ira->codegen->invalid_inst_gen;
23537 heap::c_allocator.deallocate(buf, src_size_bytes);
23538 return result;
23539 }
23540
23541 if (dest_is_ptr && !src_is_ptr) {
23542 // Spill the scalar into a local memory location and take its address
23543 value = ir_get_ref(ira, scope, source_node, value, false, false);
23544 }
23545
23546 return ir_build_bit_cast_gen(ira, scope, source_node, value, dest_type);
23547}
23548
23549static Stage1AirInst *ir_analyze_int_to_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *target,
23550 ZigType *ptr_type)
23551{
23552 Error err;
23553
23554 src_assert(get_src_ptr_type(ptr_type) != nullptr, source_node);
23555 src_assert(type_has_bits(ira->codegen, ptr_type), source_node);
23556
23557 Stage1AirInst *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
23558 if (type_is_invalid(casted_int->value->type))
23559 return ira->codegen->invalid_inst_gen;
23560
23561 if (instr_is_comptime(casted_int)) {
23562 ZigValue *val = ir_resolve_const(ira, casted_int, UndefBad);
23563 if (!val)
23564 return ira->codegen->invalid_inst_gen;
23565
23566 uint64_t addr = bigint_as_u64(&val->data.x_bigint);
23567 if (!ptr_allows_addr_zero(ptr_type) && addr == 0) {
23568 ir_add_error_node(ira, source_node,
23569 buf_sprintf("pointer type '%s' does not allow address zero", buf_ptr(&ptr_type->name)));
23570 return ira->codegen->invalid_inst_gen;
23571 }
23572
23573 uint32_t align_bytes;
23574 if ((err = resolve_ptr_align(ira, ptr_type, &align_bytes)))
23575 return ira->codegen->invalid_inst_gen;
23576
23577 if (addr != 0 && addr % align_bytes != 0) {
23578 ir_add_error_node(ira, source_node,
23579 buf_sprintf("pointer type '%s' requires aligned address",
23580 buf_ptr(&ptr_type->name)));
23581 return ira->codegen->invalid_inst_gen;
23582 }
23583
23584 Stage1AirInst *result = ir_const(ira, scope, source_node, ptr_type);
23585 if (ptr_type->id == ZigTypeIdOptional && addr == 0) {
23586 result->value->data.x_ptr.special = ConstPtrSpecialNull;
23587 result->value->data.x_ptr.mut = ConstPtrMutComptimeConst;
23588 } else {
23589 result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
23590 result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar;
23591 result->value->data.x_ptr.data.hard_coded_addr.addr = addr;
23592 }
23593
23594 return result;
23595 }
23596
23597 return ir_build_int_to_ptr_gen(ira, scope, source_node, casted_int, ptr_type);
23598}
23599
23600static Stage1AirInst *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, Stage1ZirInstIntToPtr *instruction) {
23601 Error err;
23602 Stage1AirInst *dest_type_value = instruction->dest_type->child;
23603 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
23604 if (type_is_invalid(dest_type))
23605 return ira->codegen->invalid_inst_gen;
23606
23607 // We explicitly check for the size, so we can use get_src_ptr_type
23608 if (get_src_ptr_type(dest_type) == nullptr) {
23609 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
23610 return ira->codegen->invalid_inst_gen;
23611 }
23612
23613 bool has_bits;
23614 if ((err = type_has_bits2(ira->codegen, dest_type, &has_bits)))
23615 return ira->codegen->invalid_inst_gen;
23616
23617 if (!has_bits) {
23618 ir_add_error(ira, dest_type_value,
23619 buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name)));
23620 return ira->codegen->invalid_inst_gen;
23621 }
23622
23623 Stage1AirInst *target = instruction->target->child;
23624 if (type_is_invalid(target->value->type))
23625 return ira->codegen->invalid_inst_gen;
23626
23627 return ir_analyze_int_to_ptr(ira, instruction->base.scope, instruction->base.source_node, target, dest_type);
23628}
23629
23630static Stage1AirInst *ir_analyze_instruction_decl_ref(IrAnalyze *ira, Stage1ZirInstDeclRef *instruction) {
23631 Stage1AirInst *ref_instruction = ir_analyze_decl_ref(ira, instruction->base.scope, instruction->base.source_node, instruction->tld);
23632 if (type_is_invalid(ref_instruction->value->type)) {
23633 return ira->codegen->invalid_inst_gen;
23634 }
23635
23636 if (instruction->lval == LValPtr || instruction->lval == LValAssign) {
23637 return ref_instruction;
23638 } else {
23639 return ir_get_deref(ira, instruction->base.scope, instruction->base.source_node, ref_instruction, nullptr);
23640 }
23641}
23642
23643static Stage1AirInst *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, Stage1ZirInstPtrToInt *instruction) {
23644 Error err;
23645 Stage1AirInst *target = instruction->target->child;
23646 if (type_is_invalid(target->value->type))
23647 return ira->codegen->invalid_inst_gen;
23648
23649 ZigType *usize = ira->codegen->builtin_types.entry_usize;
23650
23651 ZigType *src_ptr_type = get_src_ptr_type(target->value->type);
23652 if (src_ptr_type == nullptr) {
23653 ir_add_error(ira, target,
23654 buf_sprintf("expected pointer, found '%s'", buf_ptr(&target->value->type->name)));
23655 return ira->codegen->invalid_inst_gen;
23656 }
23657
23658 bool has_bits;
23659 if ((err = type_has_bits2(ira->codegen, src_ptr_type, &has_bits)))
23660 return ira->codegen->invalid_inst_gen;
23661
23662 if (!has_bits) {
23663 ir_add_error(ira, target,
23664 buf_sprintf("pointer to size 0 type has no address"));
23665 return ira->codegen->invalid_inst_gen;
23666 }
23667
23668 if (instr_is_comptime(target)) {
23669 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
23670 if (!val)
23671 return ira->codegen->invalid_inst_gen;
23672
23673 // Since we've already run this type trough get_src_ptr_type it is
23674 // safe to access the x_ptr fields
23675 if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
23676 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, usize);
23677 bigint_init_unsigned(&result->value->data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);
23678 result->value->type = usize;
23679 return result;
23680 } else if (val->data.x_ptr.special == ConstPtrSpecialNull) {
23681 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, usize);
23682 bigint_init_unsigned(&result->value->data.x_bigint, 0);
23683 result->value->type = usize;
23684 return result;
23685 }
23686 }
23687
23688 return ir_build_ptr_to_int_gen(ira, instruction->base.scope, instruction->base.source_node, target);
23689}
23690
23691static Stage1AirInst *ir_analyze_instruction_ptr_type_simple(IrAnalyze *ira,
23692 Stage1ZirInstPtrTypeSimple *instruction, bool is_const)
23693{
23694 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_type);
23695 result->value->special = ConstValSpecialLazy;
23696
23697 LazyValuePtrTypeSimple *lazy_ptr_type = heap::c_allocator.create<LazyValuePtrTypeSimple>();
23698 lazy_ptr_type->ira = ira; ira_ref(ira);
23699 result->value->data.x_lazy = &lazy_ptr_type->base;
23700 lazy_ptr_type->base.id = is_const ? LazyValueIdPtrTypeSimpleConst : LazyValueIdPtrTypeSimple;
23701
23702 lazy_ptr_type->elem_type = instruction->child_type->child;
23703 if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr)
23704 return ira->codegen->invalid_inst_gen;
23705
23706 return result;
23707}
23708
23709static Stage1AirInst *ir_analyze_instruction_ptr_type(IrAnalyze *ira, Stage1ZirInstPtrType *instruction) {
23710 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_type);
23711 result->value->special = ConstValSpecialLazy;
23712
23713 LazyValuePtrType *lazy_ptr_type = heap::c_allocator.create<LazyValuePtrType>();
23714 lazy_ptr_type->ira = ira; ira_ref(ira);
23715 result->value->data.x_lazy = &lazy_ptr_type->base;
23716 lazy_ptr_type->base.id = LazyValueIdPtrType;
23717
23718 if (instruction->sentinel != nullptr) {
23719 if (instruction->ptr_len != PtrLenUnknown) {
23720 ir_add_error_node(ira, instruction->base.source_node,
23721 buf_sprintf("sentinels are only allowed on unknown-length pointers"));
23722 return ira->codegen->invalid_inst_gen;
23723 }
23724
23725 lazy_ptr_type->sentinel = instruction->sentinel->child;
23726 if (ir_resolve_const(ira, lazy_ptr_type->sentinel, LazyOk) == nullptr)
23727 return ira->codegen->invalid_inst_gen;
23728 }
23729
23730 lazy_ptr_type->elem_type = instruction->child_type->child;
23731 if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr)
23732 return ira->codegen->invalid_inst_gen;
23733
23734 if (instruction->align_value != nullptr) {
23735 lazy_ptr_type->align_inst = instruction->align_value->child;
23736 if (ir_resolve_const(ira, lazy_ptr_type->align_inst, LazyOk) == nullptr)
23737 return ira->codegen->invalid_inst_gen;
23738 }
23739
23740 lazy_ptr_type->ptr_len = instruction->ptr_len;
23741 lazy_ptr_type->is_const = instruction->is_const;
23742 lazy_ptr_type->is_volatile = instruction->is_volatile;
23743 lazy_ptr_type->is_allowzero = instruction->is_allow_zero;
23744 lazy_ptr_type->bit_offset_in_host = instruction->bit_offset_start;
23745 lazy_ptr_type->host_int_bytes = instruction->host_int_bytes;
23746
23747 return result;
23748}
23749
23750static Stage1AirInst *ir_analyze_instruction_align_cast(IrAnalyze *ira, Stage1ZirInstAlignCast *instruction) {
23751 Stage1AirInst *target = instruction->target->child;
23752 if (type_is_invalid(target->value->type))
23753 return ira->codegen->invalid_inst_gen;
23754
23755 ZigType *elem_type = nullptr;
23756 if (is_slice(target->value->type)) {
23757 ZigType *slice_ptr_type = target->value->type->data.structure.fields[slice_ptr_index]->type_entry;
23758 elem_type = slice_ptr_type->data.pointer.child_type;
23759 } else if (target->value->type->id == ZigTypeIdPointer) {
23760 elem_type = target->value->type->data.pointer.child_type;
23761 }
23762
23763 uint32_t align_bytes;
23764 Stage1AirInst *align_bytes_inst = instruction->align_bytes->child;
23765 if (!ir_resolve_align(ira, align_bytes_inst, elem_type, &align_bytes))
23766 return ira->codegen->invalid_inst_gen;
23767
23768 Stage1AirInst *result = ir_align_cast(ira, target, align_bytes, true);
23769 if (type_is_invalid(result->value->type))
23770 return ira->codegen->invalid_inst_gen;
23771
23772 return result;
23773}
23774
23775static bool ir_resolve_addrspace(IrAnalyze *ira, Stage1AirInst *value, AddressSpace *out) {
23776 if (type_is_invalid(value->value->type))
23777 return false;
23778
23779 ZigType *addrspace_type = get_builtin_type(ira->codegen, "AddressSpace");
23780
23781 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, addrspace_type);
23782 if (type_is_invalid(casted_value->value->type))
23783 return false;
23784
23785 ZigValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
23786 if (!const_val)
23787 return false;
23788
23789 *out = (AddressSpace)bigint_as_u32(&const_val->data.x_enum_tag);
23790 return true;
23791}
23792
23793static Stage1AirInst *ir_analyze_instruction_addrspace_cast(IrAnalyze *ira, Stage1ZirInstAddrSpaceCast *instruction) {
23794 Stage1AirInst *ptr_inst = instruction->ptr->child;
23795 ZigType *ptr_type = ptr_inst->value->type;
23796 if (type_is_invalid(ptr_type))
23797 return ira->codegen->invalid_inst_gen;
23798
23799 AddressSpace addrspace;
23800 if (!ir_resolve_addrspace(ira, instruction->addrspace->child, &addrspace))
23801 return ira->codegen->invalid_inst_gen;
23802
23803 if (addrspace != AddressSpaceGeneric) {
23804 ir_add_error_node(ira, instruction->addrspace->source_node, buf_sprintf(
23805 "address space '%s' not available in stage 1 compiler, must be .generic",
23806 address_space_name(addrspace)));
23807 return ira->codegen->invalid_inst_gen;
23808 }
23809
23810 if (is_slice(ptr_type) || get_src_ptr_type(ptr_type) != nullptr) {
23811 ir_add_error_node(ira, instruction->ptr->source_node,
23812 buf_sprintf("expected pointer or slice, found '%s'", buf_ptr(&ptr_type->name)));
23813 return ira->codegen->invalid_inst_gen;
23814 }
23815
23816 return ptr_inst;
23817}
23818
23819static Stage1AirInst *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, Stage1ZirInstSetAlignStack *instruction) {
23820 uint32_t align_bytes;
23821 Stage1AirInst *align_bytes_inst = instruction->align_bytes->child;
23822 if (!ir_resolve_align(ira, align_bytes_inst, nullptr, &align_bytes))
23823 return ira->codegen->invalid_inst_gen;
23824
23825 if (align_bytes > 256) {
23826 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("attempt to @setAlignStack(%" PRIu32 "); maximum is 256", align_bytes));
23827 return ira->codegen->invalid_inst_gen;
23828 }
23829
23830 ZigFn *fn_entry = ira->fn;
23831 if (fn_entry == nullptr) {
23832 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("@setAlignStack outside function"));
23833 return ira->codegen->invalid_inst_gen;
23834 }
23835 if (fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionNaked) {
23836 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("@setAlignStack in naked function"));
23837 return ira->codegen->invalid_inst_gen;
23838 }
23839
23840 if (fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionInline) {
23841 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("@setAlignStack in inline function"));
23842 return ira->codegen->invalid_inst_gen;
23843 }
23844
23845 if (fn_entry->set_alignstack_node != nullptr) {
23846 ErrorMsg *msg = ir_add_error_node(ira, instruction->base.source_node,
23847 buf_sprintf("alignstack set twice"));
23848 add_error_note(ira->codegen, msg, fn_entry->set_alignstack_node, buf_sprintf("first set here"));
23849 return ira->codegen->invalid_inst_gen;
23850 }
23851
23852 fn_entry->set_alignstack_node = instruction->base.source_node;
23853 fn_entry->alignstack_value = align_bytes;
23854
23855 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
23856}
23857
23858static Stage1AirInst *ir_analyze_instruction_arg_type(IrAnalyze *ira, Stage1ZirInstArgType *instruction,
23859 bool allow_var)
23860{
23861 Stage1AirInst *fn_type_inst = instruction->fn_type->child;
23862 ZigType *fn_type = ir_resolve_type(ira, fn_type_inst);
23863 if (type_is_invalid(fn_type))
23864 return ira->codegen->invalid_inst_gen;
23865
23866 Stage1AirInst *arg_index_inst = instruction->arg_index->child;
23867 uint64_t arg_index;
23868 if (!ir_resolve_usize(ira, arg_index_inst, &arg_index))
23869 return ira->codegen->invalid_inst_gen;
23870
23871 if (fn_type->id == ZigTypeIdBoundFn) {
23872 fn_type = fn_type->data.bound_fn.fn_type;
23873 arg_index += 1;
23874 }
23875 if (fn_type->id != ZigTypeIdFn) {
23876 ir_add_error(ira, fn_type_inst, buf_sprintf("expected function, found '%s'", buf_ptr(&fn_type->name)));
23877 return ira->codegen->invalid_inst_gen;
23878 }
23879
23880 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
23881 if (arg_index >= fn_type_id->param_count) {
23882 if (allow_var) {
23883 // TODO remove this with var args
23884 return ir_const_type(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_anytype);
23885 }
23886 ir_add_error(ira, arg_index_inst,
23887 buf_sprintf("arg index %" ZIG_PRI_u64 " out of bounds; '%s' has %" ZIG_PRI_usize " argument(s)",
23888 arg_index, buf_ptr(&fn_type->name), fn_type_id->param_count));
23889 return ira->codegen->invalid_inst_gen;
23890 }
23891
23892 ZigType *result_type = fn_type_id->param_info[arg_index].type;
23893 if (result_type == nullptr) {
23894 // Args are only unresolved if our function is generic.
23895 src_assert(fn_type->data.fn.is_generic, instruction->base.source_node);
23896
23897 if (allow_var) {
23898 return ir_const_type(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_anytype);
23899 } else {
23900 ir_add_error(ira, arg_index_inst,
23901 buf_sprintf("@ArgType could not resolve the type of arg %" ZIG_PRI_u64 " because '%s' is generic",
23902 arg_index, buf_ptr(&fn_type->name)));
23903 return ira->codegen->invalid_inst_gen;
23904 }
23905 }
23906 return ir_const_type(ira, instruction->base.scope, instruction->base.source_node, result_type);
23907}
23908
23909static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, Stage1AirInst *op) {
23910 ZigType *operand_type = ir_resolve_type(ira, op);
23911 if (type_is_invalid(operand_type))
23912 return ira->codegen->builtin_types.entry_invalid;
23913
23914 if (operand_type->id == ZigTypeIdInt || operand_type->id == ZigTypeIdEnum) {
23915 ZigType *int_type;
23916 if (operand_type->id == ZigTypeIdEnum) {
23917 int_type = operand_type->data.enumeration.tag_int_type;
23918 } else {
23919 int_type = operand_type;
23920 }
23921 auto bit_count = int_type->data.integral.bit_count;
23922 uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
23923
23924 if (bit_count > max_atomic_bits) {
23925 ir_add_error(ira, op,
23926 buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type",
23927 max_atomic_bits, bit_count));
23928 return ira->codegen->builtin_types.entry_invalid;
23929 }
23930 } else if (operand_type->id == ZigTypeIdFloat) {
23931 uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
23932 if (operand_type->data.floating.bit_count > max_atomic_bits) {
23933 ir_add_error(ira, op,
23934 buf_sprintf("expected %" PRIu32 "-bit float or smaller, found %" PRIu32 "-bit float",
23935 max_atomic_bits, (uint32_t) operand_type->data.floating.bit_count));
23936 return ira->codegen->builtin_types.entry_invalid;
23937 }
23938 } else if (operand_type->id == ZigTypeIdBool) {
23939 // will be treated as u8
23940 } else {
23941 Error err;
23942 ZigType *operand_ptr_type;
23943 if ((err = get_codegen_ptr_type(ira->codegen, operand_type, &operand_ptr_type)))
23944 return ira->codegen->builtin_types.entry_invalid;
23945 if (operand_ptr_type == nullptr) {
23946 ir_add_error(ira, op,
23947 buf_sprintf("expected bool, integer, float, enum or pointer type, found '%s'",
23948 buf_ptr(&operand_type->name)));
23949 return ira->codegen->builtin_types.entry_invalid;
23950 }
23951 }
23952
23953 return operand_type;
23954}
23955
23956static Stage1AirInst *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, Stage1ZirInstAtomicRmw *instruction) {
23957 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child);
23958 if (type_is_invalid(operand_type))
23959 return ira->codegen->invalid_inst_gen;
23960
23961 Stage1AirInst *ptr_inst = instruction->ptr->child;
23962 if (type_is_invalid(ptr_inst->value->type))
23963 return ira->codegen->invalid_inst_gen;
23964
23965 // TODO let this be volatile
23966 ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, false);
23967 Stage1AirInst *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type);
23968 if (type_is_invalid(casted_ptr->value->type))
23969 return ira->codegen->invalid_inst_gen;
23970
23971 AtomicRmwOp op;
23972 if (!ir_resolve_atomic_rmw_op(ira, instruction->op->child, &op)) {
23973 return ira->codegen->invalid_inst_gen;
23974 }
23975
23976 if (operand_type->id == ZigTypeIdEnum && op != AtomicRmwOp_xchg) {
23977 ir_add_error_node(ira, instruction->op->source_node,
23978 buf_sprintf("@atomicRmw with enum only allowed with .Xchg"));
23979 return ira->codegen->invalid_inst_gen;
23980 } else if (operand_type->id == ZigTypeIdBool && op != AtomicRmwOp_xchg) {
23981 ir_add_error_node(ira, instruction->op->source_node,
23982 buf_sprintf("@atomicRmw with bool only allowed with .Xchg"));
23983 return ira->codegen->invalid_inst_gen;
23984 } else if (operand_type->id == ZigTypeIdFloat && op > AtomicRmwOp_sub) {
23985 ir_add_error_node(ira, instruction->op->source_node,
23986 buf_sprintf("@atomicRmw with float only allowed with .Xchg, .Add and .Sub"));
23987 return ira->codegen->invalid_inst_gen;
23988 }
23989
23990 Stage1AirInst *operand = instruction->operand->child;
23991 if (type_is_invalid(operand->value->type))
23992 return ira->codegen->invalid_inst_gen;
23993
23994 Stage1AirInst *casted_operand = ir_implicit_cast(ira, operand, operand_type);
23995 if (type_is_invalid(casted_operand->value->type))
23996 return ira->codegen->invalid_inst_gen;
23997
23998 AtomicOrder ordering;
23999 if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering))
24000 return ira->codegen->invalid_inst_gen;
24001 if (ordering == AtomicOrderUnordered) {
24002 ir_add_error_node(ira, instruction->ordering->source_node,
24003 buf_sprintf("@atomicRmw atomic ordering must not be Unordered"));
24004 return ira->codegen->invalid_inst_gen;
24005 }
24006
24007 // special case zero bit types
24008 switch (type_has_one_possible_value(ira->codegen, operand_type)) {
24009 case OnePossibleValueInvalid:
24010 return ira->codegen->invalid_inst_gen;
24011 case OnePossibleValueYes:
24012 return ir_const_move(ira, instruction->base.scope, instruction->base.source_node, get_the_one_possible_value(ira->codegen, operand_type));
24013 case OnePossibleValueNo:
24014 break;
24015 }
24016
24017 Scope *scope = instruction->base.scope;
24018 AstNode *source_node = instruction->base.source_node;
24019 if (instr_is_comptime(casted_operand) && instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar) {
24020 ZigValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad);
24021 if (ptr_val == nullptr)
24022 return ira->codegen->invalid_inst_gen;
24023
24024 ZigValue *op1_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
24025 if (op1_val == nullptr)
24026 return ira->codegen->invalid_inst_gen;
24027
24028 ZigValue *op2_val = ir_resolve_const(ira, casted_operand, UndefBad);
24029 if (op2_val == nullptr)
24030 return ira->codegen->invalid_inst_gen;
24031
24032 Stage1AirInst *result = ir_const(ira, scope, source_node, operand_type);
24033 copy_const_val(ira->codegen, result->value, op1_val);
24034 if (op == AtomicRmwOp_xchg) {
24035 copy_const_val(ira->codegen, op1_val, op2_val);
24036 return result;
24037 }
24038
24039 if (operand_type->id == ZigTypeIdPointer || operand_type->id == ZigTypeIdOptional) {
24040 ir_add_error_node(ira, instruction->ordering->source_node,
24041 buf_sprintf("TODO comptime @atomicRmw with pointers other than .Xchg"));
24042 return ira->codegen->invalid_inst_gen;
24043 }
24044
24045 ErrorMsg *msg;
24046 if (op == AtomicRmwOp_min || op == AtomicRmwOp_max) {
24047 IrBinOp bin_op;
24048 if (op == AtomicRmwOp_min)
24049 // store op2 if op2 < op1
24050 bin_op = IrBinOpCmpGreaterThan;
24051 else
24052 // store op2 if op2 > op1
24053 bin_op = IrBinOpCmpLessThan;
24054
24055 Stage1AirInst *dummy_value = ir_const(ira, scope, source_node, operand_type);
24056 msg = ir_eval_bin_op_cmp_scalar(ira, scope, source_node, op1_val, bin_op, op2_val, dummy_value->value);
24057 if (msg != nullptr) {
24058 return ira->codegen->invalid_inst_gen;
24059 }
24060 if (dummy_value->value->data.x_bool)
24061 copy_const_val(ira->codegen, op1_val, op2_val);
24062 } else {
24063 IrBinOp bin_op;
24064 switch (op) {
24065 case AtomicRmwOp_xchg:
24066 case AtomicRmwOp_max:
24067 case AtomicRmwOp_min:
24068 zig_unreachable();
24069 case AtomicRmwOp_add:
24070 if (operand_type->id == ZigTypeIdFloat)
24071 bin_op = IrBinOpAdd;
24072 else
24073 bin_op = IrBinOpAddWrap;
24074 break;
24075 case AtomicRmwOp_sub:
24076 if (operand_type->id == ZigTypeIdFloat)
24077 bin_op = IrBinOpSub;
24078 else
24079 bin_op = IrBinOpSubWrap;
24080 break;
24081 case AtomicRmwOp_and:
24082 case AtomicRmwOp_nand:
24083 bin_op = IrBinOpBinAnd;
24084 break;
24085 case AtomicRmwOp_or:
24086 bin_op = IrBinOpBinOr;
24087 break;
24088 case AtomicRmwOp_xor:
24089 bin_op = IrBinOpBinXor;
24090 break;
24091 }
24092 msg = ir_eval_math_op_scalar(ira, scope, source_node, operand_type, op1_val, bin_op, op2_val, op1_val);
24093 if (msg != nullptr) {
24094 return ira->codegen->invalid_inst_gen;
24095 }
24096 if (op == AtomicRmwOp_nand) {
24097 bigint_not(&op1_val->data.x_bigint, &op1_val->data.x_bigint,
24098 operand_type->data.integral.bit_count, operand_type->data.integral.is_signed);
24099 }
24100 }
24101 return result;
24102 }
24103
24104 return ir_build_atomic_rmw_gen(ira, scope, source_node, casted_ptr, casted_operand, op,
24105 ordering, operand_type);
24106}
24107
24108static Stage1AirInst *ir_analyze_instruction_atomic_load(IrAnalyze *ira, Stage1ZirInstAtomicLoad *instruction) {
24109 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child);
24110 if (type_is_invalid(operand_type))
24111 return ira->codegen->invalid_inst_gen;
24112
24113 Stage1AirInst *ptr_inst = instruction->ptr->child;
24114 if (type_is_invalid(ptr_inst->value->type))
24115 return ira->codegen->invalid_inst_gen;
24116
24117 ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, true);
24118 Stage1AirInst *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type);
24119 if (type_is_invalid(casted_ptr->value->type))
24120 return ira->codegen->invalid_inst_gen;
24121
24122 AtomicOrder ordering;
24123 if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering))
24124 return ira->codegen->invalid_inst_gen;
24125
24126 if (ordering == AtomicOrderRelease || ordering == AtomicOrderAcqRel) {
24127 src_assert(instruction->ordering != nullptr, instruction->base.source_node);
24128 ir_add_error_node(ira, instruction->ordering->source_node,
24129 buf_sprintf("@atomicLoad atomic ordering must not be Release or AcqRel"));
24130 return ira->codegen->invalid_inst_gen;
24131 }
24132
24133 if (instr_is_comptime(casted_ptr)) {
24134 Stage1AirInst *result = ir_get_deref(ira, instruction->base.scope,
24135 instruction->base.source_node, casted_ptr, nullptr);
24136 src_assert(result->value->type != nullptr, instruction->base.source_node);
24137 return result;
24138 }
24139
24140 return ir_build_atomic_load_gen(ira, instruction->base.scope, instruction->base.source_node, casted_ptr, ordering, operand_type);
24141}
24142
24143static Stage1AirInst *ir_analyze_instruction_atomic_store(IrAnalyze *ira, Stage1ZirInstAtomicStore *instruction) {
24144 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child);
24145 if (type_is_invalid(operand_type))
24146 return ira->codegen->invalid_inst_gen;
24147
24148 Stage1AirInst *ptr_inst = instruction->ptr->child;
24149 if (type_is_invalid(ptr_inst->value->type))
24150 return ira->codegen->invalid_inst_gen;
24151
24152 ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, false);
24153 Stage1AirInst *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type);
24154 if (type_is_invalid(casted_ptr->value->type))
24155 return ira->codegen->invalid_inst_gen;
24156
24157 Stage1AirInst *value = instruction->value->child;
24158 if (type_is_invalid(value->value->type))
24159 return ira->codegen->invalid_inst_gen;
24160
24161 Stage1AirInst *casted_value = ir_implicit_cast(ira, value, operand_type);
24162 if (type_is_invalid(casted_value->value->type))
24163 return ira->codegen->invalid_inst_gen;
24164
24165
24166 AtomicOrder ordering;
24167 if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering))
24168 return ira->codegen->invalid_inst_gen;
24169
24170 if (ordering == AtomicOrderAcquire || ordering == AtomicOrderAcqRel) {
24171 src_assert(instruction->ordering != nullptr, instruction->base.source_node);
24172 ir_add_error_node(ira, instruction->ordering->source_node,
24173 buf_sprintf("@atomicStore atomic ordering must not be Acquire or AcqRel"));
24174 return ira->codegen->invalid_inst_gen;
24175 }
24176
24177 // special case zero bit types
24178 switch (type_has_one_possible_value(ira->codegen, operand_type)) {
24179 case OnePossibleValueInvalid:
24180 return ira->codegen->invalid_inst_gen;
24181 case OnePossibleValueYes:
24182 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
24183 case OnePossibleValueNo:
24184 break;
24185 }
24186
24187 if (instr_is_comptime(casted_value) && instr_is_comptime(casted_ptr)) {
24188 Stage1AirInst *result = ir_analyze_store_ptr(ira, instruction->base.scope, instruction->base.source_node, casted_ptr, value, false);
24189 result->value->type = ira->codegen->builtin_types.entry_void;
24190 return result;
24191 }
24192
24193 return ir_build_atomic_store_gen(ira, instruction->base.scope, instruction->base.source_node, casted_ptr, casted_value, ordering);
24194}
24195
24196static Stage1AirInst *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, Stage1ZirInstSaveErrRetAddr *instruction) {
24197 return ir_build_save_err_ret_addr_gen(ira, instruction->base.scope, instruction->base.source_node);
24198}
24199
24200static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_node, BuiltinFnId fop, ZigType *float_type,
24201 ZigValue *op, ZigValue *out_val)
24202{
24203 assert(ira && source_node && float_type && out_val && op);
24204 assert(float_type->id == ZigTypeIdFloat ||
24205 float_type->id == ZigTypeIdComptimeFloat);
24206
24207 unsigned bits;
24208
24209 switch (float_type->id) {
24210 case ZigTypeIdComptimeFloat:
24211 bits = 128;
24212 break;
24213 case ZigTypeIdFloat:
24214 bits = float_type->data.floating.bit_count;
24215 break;
24216 default:
24217 zig_unreachable();
24218 }
24219
24220 switch (bits) {
24221 case 16: {
24222 switch (fop) {
24223 case BuiltinFnIdSqrt:
24224 out_val->data.x_f16 = f16_sqrt(op->data.x_f16);
24225 break;
24226 case BuiltinFnIdSin:
24227 out_val->data.x_f16 = zig_double_to_f16(sin(zig_f16_to_double(op->data.x_f16)));
24228 break;
24229 case BuiltinFnIdCos:
24230 out_val->data.x_f16 = zig_double_to_f16(cos(zig_f16_to_double(op->data.x_f16)));
24231 break;
24232 case BuiltinFnIdTan:
24233 out_val->data.x_f16 = zig_double_to_f16(tan(zig_f16_to_double(op->data.x_f16)));
24234 break;
24235 case BuiltinFnIdExp:
24236 out_val->data.x_f16 = zig_double_to_f16(exp(zig_f16_to_double(op->data.x_f16)));
24237 break;
24238 case BuiltinFnIdExp2:
24239 out_val->data.x_f16 = zig_double_to_f16(exp2(zig_f16_to_double(op->data.x_f16)));
24240 break;
24241 case BuiltinFnIdLog:
24242 out_val->data.x_f16 = zig_double_to_f16(log(zig_f16_to_double(op->data.x_f16)));
24243 break;
24244 case BuiltinFnIdLog10:
24245 out_val->data.x_f16 = zig_double_to_f16(log10(zig_f16_to_double(op->data.x_f16)));
24246 break;
24247 case BuiltinFnIdLog2:
24248 out_val->data.x_f16 = zig_double_to_f16(log2(zig_f16_to_double(op->data.x_f16)));
24249 break;
24250 case BuiltinFnIdFabs:
24251 out_val->data.x_f16 = zig_double_to_f16(fabs(zig_f16_to_double(op->data.x_f16)));
24252 break;
24253 case BuiltinFnIdFloor:
24254 out_val->data.x_f16 = zig_double_to_f16(floor(zig_f16_to_double(op->data.x_f16)));
24255 break;
24256 case BuiltinFnIdCeil:
24257 out_val->data.x_f16 = zig_double_to_f16(ceil(zig_f16_to_double(op->data.x_f16)));
24258 break;
24259 case BuiltinFnIdTrunc:
24260 out_val->data.x_f16 = zig_double_to_f16(trunc(zig_f16_to_double(op->data.x_f16)));
24261 break;
24262 case BuiltinFnIdNearbyInt:
24263 out_val->data.x_f16 = zig_double_to_f16(nearbyint(zig_f16_to_double(op->data.x_f16)));
24264 break;
24265 case BuiltinFnIdRound:
24266 out_val->data.x_f16 = zig_double_to_f16(round(zig_f16_to_double(op->data.x_f16)));
24267 break;
24268 default:
24269 zig_unreachable();
24270 };
24271 break;
24272 }
24273 case 32: {
24274 switch (fop) {
24275 case BuiltinFnIdSqrt:
24276 out_val->data.x_f32 = sqrtf(op->data.x_f32);
24277 break;
24278 case BuiltinFnIdSin:
24279 out_val->data.x_f32 = sinf(op->data.x_f32);
24280 break;
24281 case BuiltinFnIdCos:
24282 out_val->data.x_f32 = cosf(op->data.x_f32);
24283 break;
24284 case BuiltinFnIdTan:
24285 out_val->data.x_f32 = tanf(op->data.x_f32);
24286 break;
24287 case BuiltinFnIdExp:
24288 out_val->data.x_f32 = expf(op->data.x_f32);
24289 break;
24290 case BuiltinFnIdExp2:
24291 out_val->data.x_f32 = exp2f(op->data.x_f32);
24292 break;
24293 case BuiltinFnIdLog:
24294 out_val->data.x_f32 = logf(op->data.x_f32);
24295 break;
24296 case BuiltinFnIdLog10:
24297 out_val->data.x_f32 = log10f(op->data.x_f32);
24298 break;
24299 case BuiltinFnIdLog2:
24300 out_val->data.x_f32 = log2f(op->data.x_f32);
24301 break;
24302 case BuiltinFnIdFabs:
24303 out_val->data.x_f32 = fabsf(op->data.x_f32);
24304 break;
24305 case BuiltinFnIdFloor:
24306 out_val->data.x_f32 = floorf(op->data.x_f32);
24307 break;
24308 case BuiltinFnIdCeil:
24309 out_val->data.x_f32 = ceilf(op->data.x_f32);
24310 break;
24311 case BuiltinFnIdTrunc:
24312 out_val->data.x_f32 = truncf(op->data.x_f32);
24313 break;
24314 case BuiltinFnIdNearbyInt:
24315 out_val->data.x_f32 = nearbyintf(op->data.x_f32);
24316 break;
24317 case BuiltinFnIdRound:
24318 out_val->data.x_f32 = roundf(op->data.x_f32);
24319 break;
24320 default:
24321 zig_unreachable();
24322 };
24323 break;
24324 }
24325 case 64: {
24326 switch (fop) {
24327 case BuiltinFnIdSqrt:
24328 out_val->data.x_f64 = sqrt(op->data.x_f64);
24329 break;
24330 case BuiltinFnIdSin:
24331 out_val->data.x_f64 = sin(op->data.x_f64);
24332 break;
24333 case BuiltinFnIdCos:
24334 out_val->data.x_f64 = cos(op->data.x_f64);
24335 break;
24336 case BuiltinFnIdTan:
24337 out_val->data.x_f64 = tan(op->data.x_f64);
24338 break;
24339 case BuiltinFnIdExp:
24340 out_val->data.x_f64 = exp(op->data.x_f64);
24341 break;
24342 case BuiltinFnIdExp2:
24343 out_val->data.x_f64 = exp2(op->data.x_f64);
24344 break;
24345 case BuiltinFnIdLog:
24346 out_val->data.x_f64 = log(op->data.x_f64);
24347 break;
24348 case BuiltinFnIdLog10:
24349 out_val->data.x_f64 = log10(op->data.x_f64);
24350 break;
24351 case BuiltinFnIdLog2:
24352 out_val->data.x_f64 = log2(op->data.x_f64);
24353 break;
24354 case BuiltinFnIdFabs:
24355 out_val->data.x_f64 = fabs(op->data.x_f64);
24356 break;
24357 case BuiltinFnIdFloor:
24358 out_val->data.x_f64 = floor(op->data.x_f64);
24359 break;
24360 case BuiltinFnIdCeil:
24361 out_val->data.x_f64 = ceil(op->data.x_f64);
24362 break;
24363 case BuiltinFnIdTrunc:
24364 out_val->data.x_f64 = trunc(op->data.x_f64);
24365 break;
24366 case BuiltinFnIdNearbyInt:
24367 out_val->data.x_f64 = nearbyint(op->data.x_f64);
24368 break;
24369 case BuiltinFnIdRound:
24370 out_val->data.x_f64 = round(op->data.x_f64);
24371 break;
24372 default:
24373 zig_unreachable();
24374 }
24375 break;
24376 }
24377 case 80: {
24378 extFloat80_t *out = &out_val->data.x_f80;
24379 extFloat80_t *in = &op->data.x_f80;
24380 switch (fop) {
24381 case BuiltinFnIdSqrt:
24382 extF80M_sqrt(in, out);
24383 break;
24384 case BuiltinFnIdFabs:
24385 extF80M_abs(in, out);
24386 break;
24387 case BuiltinFnIdFloor:
24388 extF80M_roundToInt(in, softfloat_round_min, false, out);
24389 break;
24390 case BuiltinFnIdCeil:
24391 extF80M_roundToInt(in, softfloat_round_max, false, out);
24392 break;
24393 case BuiltinFnIdTrunc:
24394 extF80M_trunc(in, out);
24395 break;
24396 case BuiltinFnIdRound:
24397 extF80M_roundToInt(in, softfloat_round_near_maxMag, false, out);
24398 break;
24399 case BuiltinFnIdNearbyInt:
24400 case BuiltinFnIdSin:
24401 case BuiltinFnIdCos:
24402 case BuiltinFnIdTan:
24403 case BuiltinFnIdExp:
24404 case BuiltinFnIdExp2:
24405 case BuiltinFnIdLog:
24406 case BuiltinFnIdLog10:
24407 case BuiltinFnIdLog2:
24408 return ir_add_error_node(ira, source_node,
24409 buf_sprintf("compiler bug: TODO: implement '%s' for type '%s'. See https://github.com/ziglang/zig/issues/4026",
24410 float_un_op_to_name(fop), buf_ptr(&float_type->name)));
24411 default:
24412 zig_unreachable();
24413 }
24414 break;
24415 }
24416 case 128: {
24417 float128_t *out, *in;
24418 if (float_type->id == ZigTypeIdComptimeFloat) {
24419 out = &out_val->data.x_bigfloat.value;
24420 in = &op->data.x_bigfloat.value;
24421 } else {
24422 out = &out_val->data.x_f128;
24423 in = &op->data.x_f128;
24424 }
24425 switch (fop) {
24426 case BuiltinFnIdSqrt:
24427 f128M_sqrt(in, out);
24428 break;
24429 case BuiltinFnIdFabs:
24430 f128M_abs(in, out);
24431 break;
24432 case BuiltinFnIdFloor:
24433 f128M_roundToInt(in, softfloat_round_min, false, out);
24434 break;
24435 case BuiltinFnIdCeil:
24436 f128M_roundToInt(in, softfloat_round_max, false, out);
24437 break;
24438 case BuiltinFnIdTrunc:
24439 f128M_trunc(in, out);
24440 break;
24441 case BuiltinFnIdRound:
24442 f128M_roundToInt(in, softfloat_round_near_maxMag, false, out);
24443 break;
24444 case BuiltinFnIdNearbyInt: {
24445 float64_t f64_value = f128M_to_f64(in);
24446 double double_value;
24447 memcpy(&double_value, &f64_value, sizeof(double));
24448 double_value = nearbyint(double_value);
24449 memcpy(&f64_value, &double_value, sizeof(double));
24450 f64_to_f128M(f64_value, out);
24451 break;
24452 }
24453 case BuiltinFnIdSin: {
24454 float64_t f64_value = f128M_to_f64(in);
24455 double double_value;
24456 memcpy(&double_value, &f64_value, sizeof(double));
24457 double_value = sin(double_value);
24458 memcpy(&f64_value, &double_value, sizeof(double));
24459 f64_to_f128M(f64_value, out);
24460 break;
24461 }
24462 case BuiltinFnIdCos: {
24463 float64_t f64_value = f128M_to_f64(in);
24464 double double_value;
24465 memcpy(&double_value, &f64_value, sizeof(double));
24466 double_value = cos(double_value);
24467 memcpy(&f64_value, &double_value, sizeof(double));
24468 f64_to_f128M(f64_value, out);
24469 break;
24470 }
24471 case BuiltinFnIdTan: {
24472 float64_t f64_value = f128M_to_f64(in);
24473 double double_value;
24474 memcpy(&double_value, &f64_value, sizeof(double));
24475 double_value = tan(double_value);
24476 memcpy(&f64_value, &double_value, sizeof(double));
24477 f64_to_f128M(f64_value, out);
24478 break;
24479 }
24480 case BuiltinFnIdExp: {
24481 float64_t f64_value = f128M_to_f64(in);
24482 double double_value;
24483 memcpy(&double_value, &f64_value, sizeof(double));
24484 double_value = exp(double_value);
24485 memcpy(&f64_value, &double_value, sizeof(double));
24486 f64_to_f128M(f64_value, out);
24487 break;
24488 }
24489 case BuiltinFnIdExp2: {
24490 float64_t f64_value = f128M_to_f64(in);
24491 double double_value;
24492 memcpy(&double_value, &f64_value, sizeof(double));
24493 double_value = exp2(double_value);
24494 memcpy(&f64_value, &double_value, sizeof(double));
24495 f64_to_f128M(f64_value, out);
24496 break;
24497 }
24498 case BuiltinFnIdLog: {
24499 float64_t f64_value = f128M_to_f64(in);
24500 double double_value;
24501 memcpy(&double_value, &f64_value, sizeof(double));
24502 double_value = log(double_value);
24503 memcpy(&f64_value, &double_value, sizeof(double));
24504 f64_to_f128M(f64_value, out);
24505 break;
24506 }
24507 case BuiltinFnIdLog10: {
24508 float64_t f64_value = f128M_to_f64(in);
24509 double double_value;
24510 memcpy(&double_value, &f64_value, sizeof(double));
24511 double_value = log10(double_value);
24512 memcpy(&f64_value, &double_value, sizeof(double));
24513 f64_to_f128M(f64_value, out);
24514 break;
24515 }
24516 case BuiltinFnIdLog2: {
24517 float64_t f64_value = f128M_to_f64(in);
24518 double double_value;
24519 memcpy(&double_value, &f64_value, sizeof(double));
24520 double_value = log2(double_value);
24521 memcpy(&f64_value, &double_value, sizeof(double));
24522 f64_to_f128M(f64_value, out);
24523 break;
24524 }
24525 default:
24526 zig_unreachable();
24527 }
24528 break;
24529 }
24530 default:
24531 zig_unreachable();
24532 }
24533 out_val->special = ConstValSpecialStatic;
24534 return nullptr;
24535}
24536
24537static Stage1AirInst *ir_analyze_instruction_float_op(IrAnalyze *ira, Stage1ZirInstFloatOp *instruction) {
24538 Stage1AirInst *operand = instruction->operand->child;
24539 ZigType *operand_type = operand->value->type;
24540 if (type_is_invalid(operand_type))
24541 return ira->codegen->invalid_inst_gen;
24542
24543 // This instruction accepts floats and vectors of floats.
24544 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ?
24545 operand_type->data.vector.elem_type : operand_type;
24546
24547 if (scalar_type->id != ZigTypeIdFloat && scalar_type->id != ZigTypeIdComptimeFloat) {
24548 ir_add_error(ira, operand,
24549 buf_sprintf("expected float type, found '%s'", buf_ptr(&scalar_type->name)));
24550 return ira->codegen->invalid_inst_gen;
24551 }
24552
24553 if (instr_is_comptime(operand)) {
24554 ZigValue *operand_val = ir_resolve_const(ira, operand, UndefOk);
24555 if (operand_val == nullptr)
24556 return ira->codegen->invalid_inst_gen;
24557 if (operand_val->special == ConstValSpecialUndef)
24558 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, operand_type);
24559
24560 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, operand_type);
24561 ZigValue *out_val = result->value;
24562
24563 if (operand_type->id == ZigTypeIdVector) {
24564 expand_undef_array(ira->codegen, operand_val);
24565 out_val->special = ConstValSpecialUndef;
24566 expand_undef_array(ira->codegen, out_val);
24567 size_t len = operand_type->data.vector.len;
24568 for (size_t i = 0; i < len; i += 1) {
24569 ZigValue *elem_operand = &operand_val->data.x_array.data.s_none.elements[i];
24570 ZigValue *float_out_val = &out_val->data.x_array.data.s_none.elements[i];
24571 src_assert(elem_operand->type == scalar_type, instruction->base.source_node);
24572 src_assert(float_out_val->type == scalar_type, instruction->base.source_node);
24573 ErrorMsg *msg = ir_eval_float_op(ira, instruction->base.scope, instruction->base.source_node, instruction->fn_id, scalar_type,
24574 elem_operand, float_out_val);
24575 if (msg != nullptr) {
24576 add_error_note(ira->codegen, msg, instruction->base.source_node,
24577 buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i));
24578 return ira->codegen->invalid_inst_gen;
24579 }
24580 float_out_val->type = scalar_type;
24581 }
24582 out_val->type = operand_type;
24583 out_val->special = ConstValSpecialStatic;
24584 } else {
24585 if (ir_eval_float_op(ira, instruction->base.scope, instruction->base.source_node, instruction->fn_id, scalar_type,
24586 operand_val, out_val) != nullptr)
24587 {
24588 return ira->codegen->invalid_inst_gen;
24589 }
24590 }
24591 return result;
24592 }
24593
24594 src_assert(scalar_type->id == ZigTypeIdFloat, instruction->base.source_node);
24595
24596 return ir_build_float_op_gen(ira, instruction->base.scope, instruction->base.source_node, operand, instruction->fn_id, operand_type);
24597}
24598
24599static Stage1AirInst *ir_analyze_instruction_bswap(IrAnalyze *ira, Stage1ZirInstBswap *instruction) {
24600 Error err;
24601
24602 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
24603 if (type_is_invalid(int_type))
24604 return ira->codegen->invalid_inst_gen;
24605
24606 Stage1AirInst *uncasted_op = instruction->op->child;
24607 if (type_is_invalid(uncasted_op->value->type))
24608 return ira->codegen->invalid_inst_gen;
24609
24610 uint32_t vector_len = UINT32_MAX; // means not a vector
24611 if (uncasted_op->value->type->id == ZigTypeIdArray) {
24612 bool can_be_vec_elem;
24613 if ((err = is_valid_vector_elem_type(ira->codegen, uncasted_op->value->type->data.array.child_type,
24614 &can_be_vec_elem)))
24615 {
24616 return ira->codegen->invalid_inst_gen;
24617 }
24618 if (can_be_vec_elem) {
24619 vector_len = uncasted_op->value->type->data.array.len;
24620 }
24621 } else if (uncasted_op->value->type->id == ZigTypeIdVector) {
24622 vector_len = uncasted_op->value->type->data.vector.len;
24623 }
24624
24625 bool is_vector = (vector_len != UINT32_MAX);
24626 ZigType *op_type = is_vector ? get_vector_type(ira->codegen, vector_len, int_type) : int_type;
24627
24628 Stage1AirInst *op = ir_implicit_cast(ira, uncasted_op, op_type);
24629 if (type_is_invalid(op->value->type))
24630 return ira->codegen->invalid_inst_gen;
24631
24632 if (int_type->data.integral.bit_count == 8 || int_type->data.integral.bit_count == 0)
24633 return op;
24634
24635 if (int_type->data.integral.bit_count % 8 != 0) {
24636 ir_add_error_node(ira, instruction->op->source_node,
24637 buf_sprintf("@byteSwap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8",
24638 buf_ptr(&int_type->name), int_type->data.integral.bit_count));
24639 return ira->codegen->invalid_inst_gen;
24640 }
24641
24642 if (instr_is_comptime(op)) {
24643 ZigValue *val = ir_resolve_const(ira, op, UndefOk);
24644 if (val == nullptr)
24645 return ira->codegen->invalid_inst_gen;
24646 if (val->special == ConstValSpecialUndef)
24647 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, op_type);
24648
24649 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, op_type);
24650 const size_t buf_size = int_type->data.integral.bit_count / 8;
24651 uint8_t *buf = heap::c_allocator.allocate_nonzero<uint8_t>(buf_size);
24652 if (is_vector) {
24653 expand_undef_array(ira->codegen, val);
24654 result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(op_type->data.vector.len);
24655 for (unsigned i = 0; i < op_type->data.vector.len; i += 1) {
24656 ZigValue *op_elem_val = &val->data.x_array.data.s_none.elements[i];
24657 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.source_node,
24658 op_elem_val, UndefOk)))
24659 {
24660 return ira->codegen->invalid_inst_gen;
24661 }
24662 ZigValue *result_elem_val = &result->value->data.x_array.data.s_none.elements[i];
24663 result_elem_val->type = int_type;
24664 result_elem_val->special = op_elem_val->special;
24665 if (op_elem_val->special == ConstValSpecialUndef)
24666 continue;
24667
24668 bigint_write_twos_complement(&op_elem_val->data.x_bigint, buf, int_type->data.integral.bit_count, true);
24669 bigint_read_twos_complement(&result->value->data.x_array.data.s_none.elements[i].data.x_bigint,
24670 buf, int_type->data.integral.bit_count, false,
24671 int_type->data.integral.is_signed);
24672 }
24673 } else {
24674 bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true);
24675 bigint_read_twos_complement(&result->value->data.x_bigint, buf, int_type->data.integral.bit_count, false,
24676 int_type->data.integral.is_signed);
24677 }
24678 heap::c_allocator.deallocate(buf, buf_size);
24679 return result;
24680 }
24681
24682 return ir_build_bswap_gen(ira, instruction->base.scope, instruction->base.source_node, op_type, op);
24683}
24684
24685static Stage1AirInst *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, Stage1ZirInstBitReverse *instruction) {
24686 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
24687 if (type_is_invalid(int_type))
24688 return ira->codegen->invalid_inst_gen;
24689
24690 Stage1AirInst *op = ir_implicit_cast(ira, instruction->op->child, int_type);
24691 if (type_is_invalid(op->value->type))
24692 return ira->codegen->invalid_inst_gen;
24693
24694 if (int_type->data.integral.bit_count == 0) {
24695 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, int_type);
24696 bigint_init_unsigned(&result->value->data.x_bigint, 0);
24697 return result;
24698 }
24699
24700 if (instr_is_comptime(op)) {
24701 ZigValue *val = ir_resolve_const(ira, op, UndefOk);
24702 if (val == nullptr)
24703 return ira->codegen->invalid_inst_gen;
24704 if (val->special == ConstValSpecialUndef)
24705 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, int_type);
24706
24707 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, int_type);
24708 size_t num_bits = int_type->data.integral.bit_count;
24709 size_t buf_size = (num_bits + 7) / 8;
24710 uint8_t *comptime_buf = heap::c_allocator.allocate_nonzero<uint8_t>(buf_size);
24711 uint8_t *result_buf = heap::c_allocator.allocate_nonzero<uint8_t>(buf_size);
24712 memset(comptime_buf,0,buf_size);
24713 memset(result_buf,0,buf_size);
24714
24715 bigint_write_twos_complement(&val->data.x_bigint,comptime_buf,num_bits,ira->codegen->is_big_endian);
24716
24717 size_t bit_i = 0;
24718 size_t bit_rev_i = num_bits - 1;
24719 for (; bit_i < num_bits; bit_i++, bit_rev_i--) {
24720 if (comptime_buf[bit_i / 8] & (1 << (bit_i % 8))) {
24721 result_buf[bit_rev_i / 8] |= (1 << (bit_rev_i % 8));
24722 }
24723 }
24724
24725 bigint_read_twos_complement(&result->value->data.x_bigint,
24726 result_buf,
24727 int_type->data.integral.bit_count,
24728 ira->codegen->is_big_endian,
24729 int_type->data.integral.is_signed);
24730
24731 heap::c_allocator.deallocate(comptime_buf, buf_size);
24732 heap::c_allocator.deallocate(result_buf, buf_size);
24733 return result;
24734 }
24735
24736 return ir_build_bit_reverse_gen(ira, instruction->base.scope, instruction->base.source_node, int_type, op);
24737}
24738
24739
24740static Stage1AirInst *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, Stage1ZirInstEnumToInt *instruction) {
24741 Stage1AirInst *target = instruction->target->child;
24742 if (type_is_invalid(target->value->type))
24743 return ira->codegen->invalid_inst_gen;
24744
24745 return ir_analyze_enum_to_int(ira, instruction->base.scope, instruction->base.source_node, target);
24746}
24747
24748static Stage1AirInst *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, Stage1ZirInstIntToEnum *instruction) {
24749 Error err;
24750 Stage1AirInst *dest_type_value = instruction->dest_type->child;
24751 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
24752 if (type_is_invalid(dest_type))
24753 return ira->codegen->invalid_inst_gen;
24754
24755 if (dest_type->id != ZigTypeIdEnum) {
24756 ir_add_error_node(ira, instruction->dest_type->source_node,
24757 buf_sprintf("expected enum, found type '%s'", buf_ptr(&dest_type->name)));
24758 return ira->codegen->invalid_inst_gen;
24759 }
24760
24761 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
24762 return ira->codegen->invalid_inst_gen;
24763
24764 ZigType *tag_type = dest_type->data.enumeration.tag_int_type;
24765
24766 Stage1AirInst *target = instruction->target->child;
24767 if (type_is_invalid(target->value->type))
24768 return ira->codegen->invalid_inst_gen;
24769
24770 Stage1AirInst *casted_target = ir_analyze_int_cast(ira, instruction->base.scope,
24771 instruction->base.source_node, tag_type, instruction->dest_type->source_node,
24772 target, instruction->target->source_node);
24773 if (type_is_invalid(casted_target->value->type))
24774 return ira->codegen->invalid_inst_gen;
24775
24776 return ir_analyze_int_to_enum(ira, instruction->base.scope, instruction->base.source_node, casted_target, dest_type);
24777}
24778
24779static Stage1AirInst *ir_analyze_instruction_check_runtime_scope(IrAnalyze *ira, Stage1ZirInstCheckRuntimeScope *instruction) {
24780 Stage1AirInst *block_comptime_inst = instruction->scope_is_comptime->child;
24781 bool scope_is_comptime;
24782 if (!ir_resolve_bool(ira, block_comptime_inst, &scope_is_comptime))
24783 return ira->codegen->invalid_inst_gen;
24784
24785 Stage1AirInst *is_comptime_inst = instruction->is_comptime->child;
24786 bool is_comptime;
24787 if (!ir_resolve_bool(ira, is_comptime_inst, &is_comptime))
24788 return ira->codegen->invalid_inst_gen;
24789
24790 if (!scope_is_comptime && is_comptime) {
24791 ErrorMsg *msg = ir_add_error_node(ira, instruction->base.source_node,
24792 buf_sprintf("comptime control flow inside runtime block"));
24793 add_error_note(ira->codegen, msg, block_comptime_inst->source_node,
24794 buf_sprintf("runtime block created here"));
24795 return ira->codegen->invalid_inst_gen;
24796 }
24797
24798 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
24799}
24800
24801static Stage1AirInst *ir_analyze_instruction_has_decl(IrAnalyze *ira, Stage1ZirInstHasDecl *instruction) {
24802 ZigType *container_type = ir_resolve_type(ira, instruction->container->child);
24803 if (type_is_invalid(container_type))
24804 return ira->codegen->invalid_inst_gen;
24805
24806 Buf *name = ir_resolve_str(ira, instruction->name->child);
24807 if (name == nullptr)
24808 return ira->codegen->invalid_inst_gen;
24809
24810 if (!is_container(container_type)) {
24811 ir_add_error_node(ira, instruction->container->source_node,
24812 buf_sprintf("expected struct, enum, or union; found '%s'", buf_ptr(&container_type->name)));
24813 return ira->codegen->invalid_inst_gen;
24814 }
24815
24816 ScopeDecls *container_scope = get_container_scope(container_type);
24817 Tld *tld = find_container_decl(ira->codegen, container_scope, name);
24818 if (tld == nullptr)
24819 return ir_const_bool(ira, instruction->base.scope, instruction->base.source_node, false);
24820
24821 if (tld->visib_mod == VisibModPrivate && tld->import != get_scope_import(instruction->base.scope)) {
24822 return ir_const_bool(ira, instruction->base.scope, instruction->base.source_node, false);
24823 }
24824
24825 return ir_const_bool(ira, instruction->base.scope, instruction->base.source_node, true);
24826}
24827
24828static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode *node, Buf *var_name) {
24829 ScopeDecls *scope_decls = nullptr;
24830 while (scope != nullptr) {
24831 if (scope->id == ScopeIdDecls) {
24832 scope_decls = reinterpret_cast<ScopeDecls *>(scope);
24833 }
24834 scope = scope->parent;
24835 }
24836 TldVar *tld_var = heap::c_allocator.create<TldVar>();
24837 init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base);
24838 tld_var->base.resolution = TldResolutionInvalid;
24839 tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false,
24840 g->invalid_inst_gen->value, &tld_var->base, g->builtin_types.entry_invalid);
24841 scope_decls->decl_table.put(var_name, &tld_var->base);
24842}
24843
24844static Stage1AirInst *ir_analyze_instruction_undeclared_ident(IrAnalyze *ira, Stage1ZirInstUndeclaredIdent *instruction) {
24845 // put a variable of same name with invalid type in global scope
24846 // so that future references to this same name will find a variable with an invalid type
24847 populate_invalid_variable_in_scope(ira->codegen, instruction->base.scope,
24848 instruction->base.source_node, instruction->name);
24849 ir_add_error_node(ira, instruction->base.source_node,
24850 buf_sprintf("use of undeclared identifier '%s'", buf_ptr(instruction->name)));
24851 return ira->codegen->invalid_inst_gen;
24852}
24853
24854static Stage1AirInst *ir_analyze_instruction_end_expr(IrAnalyze *ira, Stage1ZirInstEndExpr *instruction) {
24855 Stage1AirInst *value = instruction->value->child;
24856 if (type_is_invalid(value->value->type))
24857 return ira->codegen->invalid_inst_gen;
24858
24859 bool was_written = instruction->result_loc->written;
24860 Stage1AirInst *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
24861 value->value->type, value, false, true);
24862 if (result_loc != nullptr) {
24863 if (type_is_invalid(result_loc->value->type))
24864 return ira->codegen->invalid_inst_gen;
24865 if (result_loc->value->type->id == ZigTypeIdUnreachable)
24866 return result_loc;
24867
24868 if (!was_written || instruction->result_loc->id == ResultLocIdPeer) {
24869 Stage1AirInst *store_ptr = ir_analyze_store_ptr(ira, instruction->base.scope, instruction->base.source_node, result_loc, value,
24870 instruction->result_loc->allow_write_through_const);
24871 if (type_is_invalid(store_ptr->value->type)) {
24872 if (instruction->result_loc->id == ResultLocIdReturn &&
24873 (value->value->type->id == ZigTypeIdErrorUnion || value->value->type->id == ZigTypeIdErrorSet) &&
24874 ira->explicit_return_type->id != ZigTypeIdErrorUnion && ira->explicit_return_type->id != ZigTypeIdErrorSet &&
24875 // Only add error note if we have a node to attach it to
24876 ira->explicit_return_type_source_node)
24877 {
24878 add_error_note(ira->codegen, ira->new_irb.exec->first_err_trace_msg,
24879 ira->explicit_return_type_source_node, buf_create_from_str("function cannot return an error"));
24880 }
24881 return ira->codegen->invalid_inst_gen;
24882 }
24883 }
24884
24885 if (result_loc->value->data.x_ptr.mut == ConstPtrMutInfer &&
24886 instruction->result_loc->id != ResultLocIdPeer)
24887 {
24888 if (instr_is_comptime(value)) {
24889 result_loc->value->data.x_ptr.mut = ConstPtrMutComptimeConst;
24890 } else {
24891 result_loc->value->special = ConstValSpecialRuntime;
24892 }
24893 }
24894 }
24895
24896 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
24897}
24898
24899static Stage1AirInst *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, Stage1ZirInstImplicitCast *instruction) {
24900 Stage1AirInst *operand = instruction->operand->child;
24901 if (type_is_invalid(operand->value->type))
24902 return operand;
24903
24904 ZigType *dest_type = ir_resolve_type(ira, instruction->result_loc_cast->base.source_instruction->child);
24905 if (type_is_invalid(dest_type))
24906 return ira->codegen->invalid_inst_gen;
24907 return ir_implicit_cast2(ira, instruction->base.scope, instruction->base.source_node,
24908 operand, dest_type);
24909}
24910
24911static Stage1AirInst *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, Stage1ZirInstBitCast *instruction) {
24912 Stage1AirInst *operand = instruction->operand->child;
24913 if (type_is_invalid(operand->value->type))
24914 return operand;
24915
24916 Stage1AirInst *result_loc = ir_resolve_result(ira, &instruction->base,
24917 &instruction->result_loc_bit_cast->base, operand->value->type, operand, false, true);
24918 if (result_loc != nullptr &&
24919 (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable))
24920 {
24921 return result_loc;
24922 }
24923
24924 ZigType *dest_type = ir_resolve_type(ira,
24925 instruction->result_loc_bit_cast->base.source_instruction->child);
24926 if (type_is_invalid(dest_type))
24927 return ira->codegen->invalid_inst_gen;
24928 return ir_analyze_bit_cast(ira, instruction->base.scope, instruction->base.source_node, operand, dest_type);
24929}
24930
24931static Stage1AirInst *ir_analyze_instruction_union_init_named_field(IrAnalyze *ira,
24932 Stage1ZirInstUnionInitNamedField *instruction)
24933{
24934 ZigType *union_type = ir_resolve_type(ira, instruction->union_type->child);
24935 if (type_is_invalid(union_type))
24936 return ira->codegen->invalid_inst_gen;
24937
24938 if (union_type->id != ZigTypeIdUnion) {
24939 ir_add_error_node(ira, instruction->union_type->source_node,
24940 buf_sprintf("non-union type '%s' passed to @unionInit", buf_ptr(&union_type->name)));
24941 return ira->codegen->invalid_inst_gen;
24942 }
24943
24944 Buf *field_name = ir_resolve_str(ira, instruction->field_name->child);
24945 if (field_name == nullptr)
24946 return ira->codegen->invalid_inst_gen;
24947
24948 Stage1AirInst *field_result_loc = instruction->field_result_loc->child;
24949 if (type_is_invalid(field_result_loc->value->type))
24950 return ira->codegen->invalid_inst_gen;
24951
24952 Stage1AirInst *result_loc = instruction->result_loc->child;
24953 if (type_is_invalid(result_loc->value->type))
24954 return ira->codegen->invalid_inst_gen;
24955
24956 return ir_analyze_union_init(ira, instruction->base.scope, instruction->base.source_node, instruction->base.source_node,
24957 union_type, field_name, field_result_loc, result_loc);
24958}
24959
24960static Stage1AirInst *ir_analyze_instruction_suspend_begin(IrAnalyze *ira, Stage1ZirInstSuspendBegin *instruction) {
24961 return ir_build_suspend_begin_gen(ira, instruction->base.scope, instruction->base.source_node);
24962}
24963
24964static Stage1AirInst *ir_analyze_instruction_suspend_finish(IrAnalyze *ira, Stage1ZirInstSuspendFinish *instruction) {
24965 Stage1AirInst *begin_base = instruction->begin->base.child;
24966 if (type_is_invalid(begin_base->value->type))
24967 return ira->codegen->invalid_inst_gen;
24968 src_assert(begin_base->id == Stage1AirInstIdSuspendBegin, instruction->base.source_node);
24969 Stage1AirInstSuspendBegin *begin = reinterpret_cast<Stage1AirInstSuspendBegin *>(begin_base);
24970
24971 ZigFn *fn_entry = ira->fn;
24972 src_assert(fn_entry != nullptr, instruction->base.source_node);
24973
24974 if (fn_entry->inferred_async_node == nullptr) {
24975 fn_entry->inferred_async_node = instruction->base.source_node;
24976 }
24977
24978 return ir_build_suspend_finish_gen(ira, instruction->base.scope, instruction->base.source_node, begin);
24979}
24980
24981static Stage1AirInst *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, Scope *scope, AstNode *source_node,
24982 Stage1AirInst *frame_ptr, ZigFn **target_fn)
24983{
24984 if (type_is_invalid(frame_ptr->value->type))
24985 return ira->codegen->invalid_inst_gen;
24986
24987 *target_fn = nullptr;
24988
24989 ZigType *result_type;
24990 Stage1AirInst *frame;
24991 if (frame_ptr->value->type->id == ZigTypeIdPointer &&
24992 frame_ptr->value->type->data.pointer.ptr_len == PtrLenSingle &&
24993 frame_ptr->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame)
24994 {
24995 ZigFn *func = frame_ptr->value->type->data.pointer.child_type->data.frame.fn;
24996 result_type = func->type_entry->data.fn.fn_type_id.return_type;
24997 *target_fn = func;
24998 frame = frame_ptr;
24999 } else {
25000 frame = ir_get_deref(ira, scope, source_node, frame_ptr, nullptr);
25001 if (frame->value->type->id == ZigTypeIdPointer &&
25002 frame->value->type->data.pointer.ptr_len == PtrLenSingle &&
25003 frame->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame)
25004 {
25005 ZigFn *func = frame->value->type->data.pointer.child_type->data.frame.fn;
25006 result_type = func->type_entry->data.fn.fn_type_id.return_type;
25007 *target_fn = func;
25008 } else if (frame->value->type->id != ZigTypeIdAnyFrame ||
25009 frame->value->type->data.any_frame.result_type == nullptr)
25010 {
25011 ir_add_error_node(ira, source_node,
25012 buf_sprintf("expected anyframe->T, found '%s'", buf_ptr(&frame->value->type->name)));
25013 return ira->codegen->invalid_inst_gen;
25014 } else {
25015 result_type = frame->value->type->data.any_frame.result_type;
25016 }
25017 }
25018
25019 ZigType *any_frame_type = get_any_frame_type(ira->codegen, result_type);
25020 Stage1AirInst *casted_frame = ir_implicit_cast(ira, frame, any_frame_type);
25021 if (type_is_invalid(casted_frame->value->type))
25022 return ira->codegen->invalid_inst_gen;
25023
25024 return casted_frame;
25025}
25026
25027static Stage1AirInst *ir_analyze_instruction_await(IrAnalyze *ira, Stage1ZirInstAwait *instruction) {
25028 Stage1AirInst *operand = instruction->frame->child;
25029 if (type_is_invalid(operand->value->type))
25030 return ira->codegen->invalid_inst_gen;
25031 ZigFn *target_fn;
25032 Stage1AirInst *frame = analyze_frame_ptr_to_anyframe_T(ira, instruction->base.scope, instruction->base.source_node, operand, &target_fn);
25033 if (type_is_invalid(frame->value->type))
25034 return ira->codegen->invalid_inst_gen;
25035
25036 ZigType *result_type = frame->value->type->data.any_frame.result_type;
25037
25038 ZigFn *fn_entry = ira->fn;
25039 src_assert(fn_entry != nullptr, instruction->base.source_node);
25040
25041 // If it's not @Frame(func) then it's definitely a suspend point
25042 if (target_fn == nullptr && !instruction->is_nosuspend) {
25043 if (fn_entry->inferred_async_node == nullptr) {
25044 fn_entry->inferred_async_node = instruction->base.source_node;
25045 }
25046 }
25047
25048 if (type_can_fail(result_type)) {
25049 fn_entry->calls_or_awaits_errorable_fn = true;
25050 }
25051
25052 Stage1AirInst *result_loc;
25053 if (type_has_bits(ira->codegen, result_type)) {
25054 result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
25055 result_type, nullptr, true, true);
25056 if (result_loc != nullptr &&
25057 (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable))
25058 {
25059 return result_loc;
25060 }
25061 } else {
25062 result_loc = nullptr;
25063 }
25064
25065 Stage1AirInstAwait *result = ir_build_await_gen(ira, instruction->base.scope, instruction->base.source_node, frame, result_type, result_loc,
25066 instruction->is_nosuspend);
25067 result->target_fn = target_fn;
25068 fn_entry->await_list.append(result);
25069 return ir_finish_anal(ira, &result->base);
25070}
25071
25072static Stage1AirInst *ir_analyze_instruction_resume(IrAnalyze *ira, Stage1ZirInstResume *instruction) {
25073 Stage1AirInst *frame_ptr = instruction->frame->child;
25074 if (type_is_invalid(frame_ptr->value->type))
25075 return ira->codegen->invalid_inst_gen;
25076
25077 Stage1AirInst *frame;
25078 if (frame_ptr->value->type->id == ZigTypeIdPointer &&
25079 frame_ptr->value->type->data.pointer.ptr_len == PtrLenSingle &&
25080 frame_ptr->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame)
25081 {
25082 frame = frame_ptr;
25083 } else {
25084 frame = ir_get_deref(ira, instruction->base.scope, instruction->base.source_node,
25085 frame_ptr, nullptr);
25086 }
25087
25088 ZigType *any_frame_type = get_any_frame_type(ira->codegen, nullptr);
25089 Stage1AirInst *casted_frame = ir_implicit_cast2(ira, instruction->frame->scope,
25090 instruction->frame->source_node, frame, any_frame_type);
25091 if (type_is_invalid(casted_frame->value->type))
25092 return ira->codegen->invalid_inst_gen;
25093
25094 return ir_build_resume_gen(ira, instruction->base.scope, instruction->base.source_node, casted_frame);
25095}
25096
25097static Stage1AirInst *ir_analyze_instruction_spill_begin(IrAnalyze *ira, Stage1ZirInstSpillBegin *instruction) {
25098 if (ir_should_inline(ira->zir, instruction->base.scope))
25099 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
25100
25101 Stage1AirInst *operand = instruction->operand->child;
25102 if (type_is_invalid(operand->value->type))
25103 return ira->codegen->invalid_inst_gen;
25104
25105 if (!type_has_bits(ira->codegen, operand->value->type))
25106 return ir_const_void(ira, instruction->base.scope, instruction->base.source_node);
25107
25108 switch (instruction->spill_id) {
25109 case SpillIdInvalid:
25110 zig_unreachable();
25111 case SpillIdRetErrCode:
25112 ira->new_irb.exec->need_err_code_spill = true;
25113 break;
25114 }
25115
25116 return ir_build_spill_begin_gen(ira, instruction->base.scope, instruction->base.source_node, operand, instruction->spill_id);
25117}
25118
25119static Stage1AirInst *ir_analyze_instruction_spill_end(IrAnalyze *ira, Stage1ZirInstSpillEnd *instruction) {
25120 Stage1AirInst *operand = instruction->begin->operand->child;
25121 if (type_is_invalid(operand->value->type))
25122 return ira->codegen->invalid_inst_gen;
25123
25124 if (ir_should_inline(ira->zir, instruction->base.scope) ||
25125 !type_has_bits(ira->codegen, operand->value->type) ||
25126 instr_is_comptime(operand))
25127 {
25128 return operand;
25129 }
25130
25131 src_assert(instruction->begin->base.child->id == Stage1AirInstIdSpillBegin, instruction->base.source_node);
25132 Stage1AirInstSpillBegin *begin = reinterpret_cast<Stage1AirInstSpillBegin *>(instruction->begin->base.child);
25133
25134 return ir_build_spill_end_gen(ira, instruction->base.scope, instruction->base.source_node, begin, operand->value->type);
25135}
25136
25137static Stage1AirInst *ir_analyze_instruction_src(IrAnalyze *ira, Stage1ZirInstSrc *instruction) {
25138 ZigFn *fn_entry = scope_fn_entry(instruction->base.scope);
25139 if (fn_entry == nullptr) {
25140 ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("@src outside function"));
25141 return ira->codegen->invalid_inst_gen;
25142 }
25143
25144 ZigType *source_location_type = get_builtin_type(ira->codegen, "SourceLocation");
25145 if (type_resolve(ira->codegen, source_location_type, ResolveStatusSizeKnown)) {
25146 zig_unreachable();
25147 }
25148
25149 ZigValue *result = ira->codegen->pass1_arena->create<ZigValue>();
25150 result->special = ConstValSpecialStatic;
25151 result->type = source_location_type;
25152
25153 ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 4);
25154 result->data.x_struct.fields = fields;
25155
25156 // file: [:0]const u8
25157 ensure_field_index(source_location_type, "file", 0);
25158 fields[0]->special = ConstValSpecialStatic;
25159
25160 ZigType *import = instruction->base.source_node->owner;
25161 RootStruct *root_struct = import->data.structure.root_struct;
25162 Buf *path = root_struct->path;
25163 fields[0] = create_sentineled_str_lit(
25164 ira->codegen, path,
25165 ira->codegen->intern.for_zero_byte());
25166
25167 // fn_name: [:0]const u8
25168 ensure_field_index(source_location_type, "fn_name", 1);
25169 fields[1]->special = ConstValSpecialStatic;
25170 fields[1] = create_sentineled_str_lit(
25171 ira->codegen, &fn_entry->symbol_name,
25172 ira->codegen->intern.for_zero_byte());
25173
25174 TokenLoc tok_loc = root_struct->token_locs[instruction->base.source_node->main_token];
25175
25176 // line: u32
25177 ensure_field_index(source_location_type, "line", 2);
25178 fields[2]->special = ConstValSpecialStatic;
25179 fields[2]->type = ira->codegen->builtin_types.entry_u32;
25180 bigint_init_unsigned(&fields[2]->data.x_bigint, tok_loc.line + 1);
25181
25182 // column: u32
25183 ensure_field_index(source_location_type, "column", 3);
25184 fields[3]->special = ConstValSpecialStatic;
25185 fields[3]->type = ira->codegen->builtin_types.entry_u32;
25186 bigint_init_unsigned(&fields[3]->data.x_bigint, tok_loc.column + 1);
25187
25188 return ir_const_move(ira, instruction->base.scope, instruction->base.source_node, result);
25189}
25190
25191static Stage1AirInst *ir_analyze_instruction_prefetch(IrAnalyze *ira, Stage1ZirInstPrefetch *instruction) {
25192 Stage1AirInst *ptr = instruction->ptr->child;
25193 if (type_is_invalid(ptr->value->type))
25194 return ira->codegen->invalid_inst_gen;
25195
25196 Stage1AirInst *raw_options_inst = instruction->options->child;
25197 if (type_is_invalid(raw_options_inst->value->type))
25198 return ira->codegen->invalid_inst_gen;
25199
25200 ZigType *options_type = get_builtin_type(ira->codegen, "PrefetchOptions");
25201 Stage1AirInst *options_inst = ir_implicit_cast(ira, raw_options_inst, options_type);
25202 if (type_is_invalid(options_inst->value->type))
25203 return ira->codegen->invalid_inst_gen;
25204
25205 ZigValue *options_val = ir_resolve_const(ira, options_inst, UndefBad);
25206 if (options_val == nullptr)
25207 return ira->codegen->invalid_inst_gen;
25208
25209 ZigValue *rw_val = get_const_field(ira, options_inst->source_node, options_val, "rw", 0);
25210 if (rw_val == nullptr)
25211 return ira->codegen->invalid_inst_gen;
25212 PrefetchRw rw = (PrefetchRw)bigint_as_u8(&rw_val->data.x_enum_tag);
25213
25214 ZigValue *locality_val = get_const_field(ira, options_inst->source_node, options_val, "locality", 1);
25215 if (locality_val == nullptr)
25216 return ira->codegen->invalid_inst_gen;
25217 uint8_t locality = bigint_as_u8(&locality_val->data.x_bigint);
25218 assert(locality <= 3);
25219
25220 ZigValue *cache_val = get_const_field(ira, options_inst->source_node, options_val, "cache", 2);
25221 if (cache_val == nullptr)
25222 return ira->codegen->invalid_inst_gen;
25223 PrefetchCache cache = (PrefetchCache)bigint_as_u8(&cache_val->data.x_enum_tag);
25224
25225 Stage1AirInstPrefetch *air_instruction = ir_build_inst_void<Stage1AirInstPrefetch>(&ira->new_irb,
25226 instruction->base.scope, instruction->base.source_node);
25227 air_instruction->ptr = ptr;
25228 air_instruction->rw = rw;
25229 air_instruction->locality = locality;
25230 air_instruction->cache = cache;
25231
25232 ir_ref_inst_gen(ptr);
25233
25234 return &air_instruction->base;
25235}
25236
25237static Stage1AirInst *ir_analyze_instruction_base(IrAnalyze *ira, Stage1ZirInst *instruction) {
25238 switch (instruction->id) {
25239 case Stage1ZirInstIdInvalid:
25240 zig_unreachable();
25241
25242 case Stage1ZirInstIdReturn:
25243 return ir_analyze_instruction_return(ira, (Stage1ZirInstReturn *)instruction);
25244 case Stage1ZirInstIdConst:
25245 return ir_analyze_instruction_const(ira, (Stage1ZirInstConst *)instruction);
25246 case Stage1ZirInstIdUnOp:
25247 return ir_analyze_instruction_un_op(ira, (Stage1ZirInstUnOp *)instruction);
25248 case Stage1ZirInstIdBinOp:
25249 return ir_analyze_instruction_bin_op(ira, (Stage1ZirInstBinOp *)instruction);
25250 case Stage1ZirInstIdMergeErrSets:
25251 return ir_analyze_instruction_merge_err_sets(ira, (Stage1ZirInstMergeErrSets *)instruction);
25252 case Stage1ZirInstIdDeclVar:
25253 return ir_analyze_instruction_decl_var(ira, (Stage1ZirInstDeclVar *)instruction);
25254 case Stage1ZirInstIdLoadPtr:
25255 return ir_analyze_instruction_load_ptr(ira, (Stage1ZirInstLoadPtr *)instruction);
25256 case Stage1ZirInstIdStorePtr:
25257 return ir_analyze_instruction_store_ptr(ira, (Stage1ZirInstStorePtr *)instruction);
25258 case Stage1ZirInstIdElemPtr:
25259 return ir_analyze_instruction_elem_ptr(ira, (Stage1ZirInstElemPtr *)instruction);
25260 case Stage1ZirInstIdVarPtr:
25261 return ir_analyze_instruction_var_ptr(ira, (Stage1ZirInstVarPtr *)instruction);
25262 case Stage1ZirInstIdFieldPtr:
25263 return ir_analyze_instruction_field_ptr(ira, (Stage1ZirInstFieldPtr *)instruction);
25264 case Stage1ZirInstIdCall:
25265 return ir_analyze_instruction_call(ira, (Stage1ZirInstCall *)instruction);
25266 case Stage1ZirInstIdCallArgs:
25267 return ir_analyze_instruction_call_args(ira, (Stage1ZirInstCallArgs *)instruction);
25268 case Stage1ZirInstIdCallExtra:
25269 return ir_analyze_instruction_call_extra(ira, (Stage1ZirInstCallExtra *)instruction);
25270 case Stage1ZirInstIdAsyncCallExtra:
25271 return ir_analyze_instruction_async_call_extra(ira, (Stage1ZirInstAsyncCallExtra *)instruction);
25272 case Stage1ZirInstIdBr:
25273 return ir_analyze_instruction_br(ira, (Stage1ZirInstBr *)instruction);
25274 case Stage1ZirInstIdCondBr:
25275 return ir_analyze_instruction_cond_br(ira, (Stage1ZirInstCondBr *)instruction);
25276 case Stage1ZirInstIdUnreachable:
25277 return ir_analyze_instruction_unreachable(ira, (Stage1ZirInstUnreachable *)instruction);
25278 case Stage1ZirInstIdPhi:
25279 return ir_analyze_instruction_phi(ira, (Stage1ZirInstPhi *)instruction);
25280 case Stage1ZirInstIdTypeOf:
25281 return ir_analyze_instruction_typeof(ira, (Stage1ZirInstTypeOf *)instruction);
25282 case Stage1ZirInstIdSetCold:
25283 return ir_analyze_instruction_set_cold(ira, (Stage1ZirInstSetCold *)instruction);
25284 case Stage1ZirInstIdSetRuntimeSafety:
25285 return ir_analyze_instruction_set_runtime_safety(ira, (Stage1ZirInstSetRuntimeSafety *)instruction);
25286 case Stage1ZirInstIdSetFloatMode:
25287 return ir_analyze_instruction_set_float_mode(ira, (Stage1ZirInstSetFloatMode *)instruction);
25288 case Stage1ZirInstIdAnyFrameType:
25289 return ir_analyze_instruction_any_frame_type(ira, (Stage1ZirInstAnyFrameType *)instruction);
25290 case Stage1ZirInstIdSliceType:
25291 return ir_analyze_instruction_slice_type(ira, (Stage1ZirInstSliceType *)instruction);
25292 case Stage1ZirInstIdAsm:
25293 return ir_analyze_instruction_asm(ira, (Stage1ZirInstAsm *)instruction);
25294 case Stage1ZirInstIdArrayType:
25295 return ir_analyze_instruction_array_type(ira, (Stage1ZirInstArrayType *)instruction);
25296 case Stage1ZirInstIdSizeOf:
25297 return ir_analyze_instruction_size_of(ira, (Stage1ZirInstSizeOf *)instruction);
25298 case Stage1ZirInstIdTestNonNull:
25299 return ir_analyze_instruction_test_non_null(ira, (Stage1ZirInstTestNonNull *)instruction);
25300 case Stage1ZirInstIdOptionalUnwrapPtr:
25301 return ir_analyze_instruction_optional_unwrap_ptr(ira, (Stage1ZirInstOptionalUnwrapPtr *)instruction);
25302 case Stage1ZirInstIdClz:
25303 return ir_analyze_instruction_clz(ira, (Stage1ZirInstClz *)instruction);
25304 case Stage1ZirInstIdCtz:
25305 return ir_analyze_instruction_ctz(ira, (Stage1ZirInstCtz *)instruction);
25306 case Stage1ZirInstIdPopCount:
25307 return ir_analyze_instruction_pop_count(ira, (Stage1ZirInstPopCount *)instruction);
25308 case Stage1ZirInstIdBswap:
25309 return ir_analyze_instruction_bswap(ira, (Stage1ZirInstBswap *)instruction);
25310 case Stage1ZirInstIdBitReverse:
25311 return ir_analyze_instruction_bit_reverse(ira, (Stage1ZirInstBitReverse *)instruction);
25312 case Stage1ZirInstIdSwitchBr:
25313 return ir_analyze_instruction_switch_br(ira, (Stage1ZirInstSwitchBr *)instruction);
25314 case Stage1ZirInstIdSwitchTarget:
25315 return ir_analyze_instruction_switch_target(ira, (Stage1ZirInstSwitchTarget *)instruction);
25316 case Stage1ZirInstIdSwitchVar:
25317 return ir_analyze_instruction_switch_var(ira, (Stage1ZirInstSwitchVar *)instruction);
25318 case Stage1ZirInstIdSwitchElseVar:
25319 return ir_analyze_instruction_switch_else_var(ira, (Stage1ZirInstSwitchElseVar *)instruction);
25320 case Stage1ZirInstIdImport:
25321 return ir_analyze_instruction_import(ira, (Stage1ZirInstImport *)instruction);
25322 case Stage1ZirInstIdRef:
25323 return ir_analyze_instruction_ref(ira, (Stage1ZirInstRef *)instruction);
25324 case Stage1ZirInstIdContainerInitList:
25325 return ir_analyze_instruction_container_init_list(ira, (Stage1ZirInstContainerInitList *)instruction);
25326 case Stage1ZirInstIdContainerInitFields:
25327 return ir_analyze_instruction_container_init_fields(ira, (Stage1ZirInstContainerInitFields *)instruction);
25328 case Stage1ZirInstIdCompileErr:
25329 return ir_analyze_instruction_compile_err(ira, (Stage1ZirInstCompileErr *)instruction);
25330 case Stage1ZirInstIdCompileLog:
25331 return ir_analyze_instruction_compile_log(ira, (Stage1ZirInstCompileLog *)instruction);
25332 case Stage1ZirInstIdErrName:
25333 return ir_analyze_instruction_err_name(ira, (Stage1ZirInstErrName *)instruction);
25334 case Stage1ZirInstIdTypeName:
25335 return ir_analyze_instruction_type_name(ira, (Stage1ZirInstTypeName *)instruction);
25336 case Stage1ZirInstIdCImport:
25337 return ir_analyze_instruction_c_import(ira, (Stage1ZirInstCImport *)instruction);
25338 case Stage1ZirInstIdCInclude:
25339 return ir_analyze_instruction_c_include(ira, (Stage1ZirInstCInclude *)instruction);
25340 case Stage1ZirInstIdCDefine:
25341 return ir_analyze_instruction_c_define(ira, (Stage1ZirInstCDefine *)instruction);
25342 case Stage1ZirInstIdCUndef:
25343 return ir_analyze_instruction_c_undef(ira, (Stage1ZirInstCUndef *)instruction);
25344 case Stage1ZirInstIdEmbedFile:
25345 return ir_analyze_instruction_embed_file(ira, (Stage1ZirInstEmbedFile *)instruction);
25346 case Stage1ZirInstIdCmpxchg:
25347 return ir_analyze_instruction_cmpxchg(ira, (Stage1ZirInstCmpxchg *)instruction);
25348 case Stage1ZirInstIdFence:
25349 return ir_analyze_instruction_fence(ira, (Stage1ZirInstFence *)instruction);
25350 case Stage1ZirInstIdReduce:
25351 return ir_analyze_instruction_reduce(ira, (Stage1ZirInstReduce *)instruction);
25352 case Stage1ZirInstIdTruncate:
25353 return ir_analyze_instruction_truncate(ira, (Stage1ZirInstTruncate *)instruction);
25354 case Stage1ZirInstIdIntCast:
25355 return ir_analyze_instruction_int_cast(ira, (Stage1ZirInstIntCast *)instruction);
25356 case Stage1ZirInstIdFloatCast:
25357 return ir_analyze_instruction_float_cast(ira, (Stage1ZirInstFloatCast *)instruction);
25358 case Stage1ZirInstIdErrSetCast:
25359 return ir_analyze_instruction_err_set_cast(ira, (Stage1ZirInstErrSetCast *)instruction);
25360 case Stage1ZirInstIdIntToFloat:
25361 return ir_analyze_instruction_int_to_float(ira, (Stage1ZirInstIntToFloat *)instruction);
25362 case Stage1ZirInstIdFloatToInt:
25363 return ir_analyze_instruction_float_to_int(ira, (Stage1ZirInstFloatToInt *)instruction);
25364 case Stage1ZirInstIdBoolToInt:
25365 return ir_analyze_instruction_bool_to_int(ira, (Stage1ZirInstBoolToInt *)instruction);
25366 case Stage1ZirInstIdVectorType:
25367 return ir_analyze_instruction_vector_type(ira, (Stage1ZirInstVectorType *)instruction);
25368 case Stage1ZirInstIdShuffleVector:
25369 return ir_analyze_instruction_shuffle_vector(ira, (Stage1ZirInstShuffleVector *)instruction);
25370 case Stage1ZirInstIdSelect:
25371 return ir_analyze_instruction_select(ira, (Stage1ZirInstSelect *)instruction);
25372 case Stage1ZirInstIdSplat:
25373 return ir_analyze_instruction_splat(ira, (Stage1ZirInstSplat *)instruction);
25374 case Stage1ZirInstIdBoolNot:
25375 return ir_analyze_instruction_bool_not(ira, (Stage1ZirInstBoolNot *)instruction);
25376 case Stage1ZirInstIdMemset:
25377 return ir_analyze_instruction_memset(ira, (Stage1ZirInstMemset *)instruction);
25378 case Stage1ZirInstIdMemcpy:
25379 return ir_analyze_instruction_memcpy(ira, (Stage1ZirInstMemcpy *)instruction);
25380 case Stage1ZirInstIdSlice:
25381 return ir_analyze_instruction_slice(ira, (Stage1ZirInstSlice *)instruction);
25382 case Stage1ZirInstIdBreakpoint:
25383 return ir_analyze_instruction_breakpoint(ira, (Stage1ZirInstBreakpoint *)instruction);
25384 case Stage1ZirInstIdReturnAddress:
25385 return ir_analyze_instruction_return_address(ira, (Stage1ZirInstReturnAddress *)instruction);
25386 case Stage1ZirInstIdFrameAddress:
25387 return ir_analyze_instruction_frame_address(ira, (Stage1ZirInstFrameAddress *)instruction);
25388 case Stage1ZirInstIdFrameHandle:
25389 return ir_analyze_instruction_frame_handle(ira, (Stage1ZirInstFrameHandle *)instruction);
25390 case Stage1ZirInstIdFrameType:
25391 return ir_analyze_instruction_frame_type(ira, (Stage1ZirInstFrameType *)instruction);
25392 case Stage1ZirInstIdFrameSize:
25393 return ir_analyze_instruction_frame_size(ira, (Stage1ZirInstFrameSize *)instruction);
25394 case Stage1ZirInstIdAlignOf:
25395 return ir_analyze_instruction_align_of(ira, (Stage1ZirInstAlignOf *)instruction);
25396 case Stage1ZirInstIdOverflowOp:
25397 return ir_analyze_instruction_overflow_op(ira, (Stage1ZirInstOverflowOp *)instruction);
25398 case Stage1ZirInstIdTestErr:
25399 return ir_analyze_instruction_test_err(ira, (Stage1ZirInstTestErr *)instruction);
25400 case Stage1ZirInstIdUnwrapErrCode:
25401 return ir_analyze_instruction_unwrap_err_code(ira, (Stage1ZirInstUnwrapErrCode *)instruction);
25402 case Stage1ZirInstIdUnwrapErrPayload:
25403 return ir_analyze_instruction_unwrap_err_payload(ira, (Stage1ZirInstUnwrapErrPayload *)instruction);
25404 case Stage1ZirInstIdFnProto:
25405 return ir_analyze_instruction_fn_proto(ira, (Stage1ZirInstFnProto *)instruction);
25406 case Stage1ZirInstIdTestComptime:
25407 return ir_analyze_instruction_test_comptime(ira, (Stage1ZirInstTestComptime *)instruction);
25408 case Stage1ZirInstIdCheckSwitchProngsUnderNo:
25409 return ir_analyze_instruction_check_switch_prongs(ira, (Stage1ZirInstCheckSwitchProngs *)instruction, false);
25410 case Stage1ZirInstIdCheckSwitchProngsUnderYes:
25411 return ir_analyze_instruction_check_switch_prongs(ira, (Stage1ZirInstCheckSwitchProngs *)instruction, true);
25412 case Stage1ZirInstIdCheckStatementIsVoid:
25413 return ir_analyze_instruction_check_statement_is_void(ira, (Stage1ZirInstCheckStatementIsVoid *)instruction);
25414 case Stage1ZirInstIdDeclRef:
25415 return ir_analyze_instruction_decl_ref(ira, (Stage1ZirInstDeclRef *)instruction);
25416 case Stage1ZirInstIdPanic:
25417 return ir_analyze_instruction_panic(ira, (Stage1ZirInstPanic *)instruction);
25418 case Stage1ZirInstIdPtrCast:
25419 return ir_analyze_instruction_ptr_cast(ira, (Stage1ZirInstPtrCast *)instruction);
25420 case Stage1ZirInstIdIntToPtr:
25421 return ir_analyze_instruction_int_to_ptr(ira, (Stage1ZirInstIntToPtr *)instruction);
25422 case Stage1ZirInstIdPtrToInt:
25423 return ir_analyze_instruction_ptr_to_int(ira, (Stage1ZirInstPtrToInt *)instruction);
25424 case Stage1ZirInstIdTagName:
25425 return ir_analyze_instruction_enum_tag_name(ira, (Stage1ZirInstTagName *)instruction);
25426 case Stage1ZirInstIdFieldParentPtr:
25427 return ir_analyze_instruction_field_parent_ptr(ira, (Stage1ZirInstFieldParentPtr *)instruction);
25428 case Stage1ZirInstIdOffsetOf:
25429 return ir_analyze_instruction_offset_of(ira, (Stage1ZirInstOffsetOf *)instruction);
25430 case Stage1ZirInstIdBitOffsetOf:
25431 return ir_analyze_instruction_bit_offset_of(ira, (Stage1ZirInstBitOffsetOf *)instruction);
25432 case Stage1ZirInstIdTypeInfo:
25433 return ir_analyze_instruction_type_info(ira, (Stage1ZirInstTypeInfo *) instruction);
25434 case Stage1ZirInstIdType:
25435 return ir_analyze_instruction_type(ira, (Stage1ZirInstType *)instruction);
25436 case Stage1ZirInstIdHasField:
25437 return ir_analyze_instruction_has_field(ira, (Stage1ZirInstHasField *) instruction);
25438 case Stage1ZirInstIdSetEvalBranchQuota:
25439 return ir_analyze_instruction_set_eval_branch_quota(ira, (Stage1ZirInstSetEvalBranchQuota *)instruction);
25440 case Stage1ZirInstIdPtrType:
25441 return ir_analyze_instruction_ptr_type(ira, (Stage1ZirInstPtrType *)instruction);
25442 case Stage1ZirInstIdPtrTypeSimple:
25443 return ir_analyze_instruction_ptr_type_simple(ira, (Stage1ZirInstPtrTypeSimple *)instruction, false);
25444 case Stage1ZirInstIdPtrTypeSimpleConst:
25445 return ir_analyze_instruction_ptr_type_simple(ira, (Stage1ZirInstPtrTypeSimple *)instruction, true);
25446 case Stage1ZirInstIdAlignCast:
25447 return ir_analyze_instruction_align_cast(ira, (Stage1ZirInstAlignCast *)instruction);
25448 case Stage1ZirInstIdImplicitCast:
25449 return ir_analyze_instruction_implicit_cast(ira, (Stage1ZirInstImplicitCast *)instruction);
25450 case Stage1ZirInstIdResolveResult:
25451 return ir_analyze_instruction_resolve_result(ira, (Stage1ZirInstResolveResult *)instruction);
25452 case Stage1ZirInstIdResetResult:
25453 return ir_analyze_instruction_reset_result(ira, (Stage1ZirInstResetResult *)instruction);
25454 case Stage1ZirInstIdSetAlignStack:
25455 return ir_analyze_instruction_set_align_stack(ira, (Stage1ZirInstSetAlignStack *)instruction);
25456 case Stage1ZirInstIdArgTypeAllowVarFalse:
25457 return ir_analyze_instruction_arg_type(ira, (Stage1ZirInstArgType *)instruction, false);
25458 case Stage1ZirInstIdArgTypeAllowVarTrue:
25459 return ir_analyze_instruction_arg_type(ira, (Stage1ZirInstArgType *)instruction, true);
25460 case Stage1ZirInstIdExport:
25461 return ir_analyze_instruction_export(ira, (Stage1ZirInstExport *)instruction);
25462 case Stage1ZirInstIdExtern:
25463 return ir_analyze_instruction_extern(ira, (Stage1ZirInstExtern *)instruction);
25464 case Stage1ZirInstIdErrorReturnTrace:
25465 return ir_analyze_instruction_error_return_trace(ira, (Stage1ZirInstErrorReturnTrace *)instruction);
25466 case Stage1ZirInstIdErrorUnion:
25467 return ir_analyze_instruction_error_union(ira, (Stage1ZirInstErrorUnion *)instruction);
25468 case Stage1ZirInstIdAtomicRmw:
25469 return ir_analyze_instruction_atomic_rmw(ira, (Stage1ZirInstAtomicRmw *)instruction);
25470 case Stage1ZirInstIdAtomicLoad:
25471 return ir_analyze_instruction_atomic_load(ira, (Stage1ZirInstAtomicLoad *)instruction);
25472 case Stage1ZirInstIdAtomicStore:
25473 return ir_analyze_instruction_atomic_store(ira, (Stage1ZirInstAtomicStore *)instruction);
25474 case Stage1ZirInstIdSaveErrRetAddr:
25475 return ir_analyze_instruction_save_err_ret_addr(ira, (Stage1ZirInstSaveErrRetAddr *)instruction);
25476 case Stage1ZirInstIdAddImplicitReturnType:
25477 return ir_analyze_instruction_add_implicit_return_type(ira, (Stage1ZirInstAddImplicitReturnType *)instruction);
25478 case Stage1ZirInstIdFloatOp:
25479 return ir_analyze_instruction_float_op(ira, (Stage1ZirInstFloatOp *)instruction);
25480 case Stage1ZirInstIdMulAdd:
25481 return ir_analyze_instruction_mul_add(ira, (Stage1ZirInstMulAdd *)instruction);
25482 case Stage1ZirInstIdIntToErr:
25483 return ir_analyze_instruction_int_to_err(ira, (Stage1ZirInstIntToErr *)instruction);
25484 case Stage1ZirInstIdErrToInt:
25485 return ir_analyze_instruction_err_to_int(ira, (Stage1ZirInstErrToInt *)instruction);
25486 case Stage1ZirInstIdIntToEnum:
25487 return ir_analyze_instruction_int_to_enum(ira, (Stage1ZirInstIntToEnum *)instruction);
25488 case Stage1ZirInstIdEnumToInt:
25489 return ir_analyze_instruction_enum_to_int(ira, (Stage1ZirInstEnumToInt *)instruction);
25490 case Stage1ZirInstIdCheckRuntimeScope:
25491 return ir_analyze_instruction_check_runtime_scope(ira, (Stage1ZirInstCheckRuntimeScope *)instruction);
25492 case Stage1ZirInstIdHasDecl:
25493 return ir_analyze_instruction_has_decl(ira, (Stage1ZirInstHasDecl *)instruction);
25494 case Stage1ZirInstIdUndeclaredIdent:
25495 return ir_analyze_instruction_undeclared_ident(ira, (Stage1ZirInstUndeclaredIdent *)instruction);
25496 case Stage1ZirInstIdAlloca:
25497 return nullptr;
25498 case Stage1ZirInstIdEndExpr:
25499 return ir_analyze_instruction_end_expr(ira, (Stage1ZirInstEndExpr *)instruction);
25500 case Stage1ZirInstIdBitCast:
25501 return ir_analyze_instruction_bit_cast_src(ira, (Stage1ZirInstBitCast *)instruction);
25502 case Stage1ZirInstIdUnionInitNamedField:
25503 return ir_analyze_instruction_union_init_named_field(ira, (Stage1ZirInstUnionInitNamedField *)instruction);
25504 case Stage1ZirInstIdSuspendBegin:
25505 return ir_analyze_instruction_suspend_begin(ira, (Stage1ZirInstSuspendBegin *)instruction);
25506 case Stage1ZirInstIdSuspendFinish:
25507 return ir_analyze_instruction_suspend_finish(ira, (Stage1ZirInstSuspendFinish *)instruction);
25508 case Stage1ZirInstIdResume:
25509 return ir_analyze_instruction_resume(ira, (Stage1ZirInstResume *)instruction);
25510 case Stage1ZirInstIdAwait:
25511 return ir_analyze_instruction_await(ira, (Stage1ZirInstAwait *)instruction);
25512 case Stage1ZirInstIdSpillBegin:
25513 return ir_analyze_instruction_spill_begin(ira, (Stage1ZirInstSpillBegin *)instruction);
25514 case Stage1ZirInstIdSpillEnd:
25515 return ir_analyze_instruction_spill_end(ira, (Stage1ZirInstSpillEnd *)instruction);
25516 case Stage1ZirInstIdWasmMemorySize:
25517 return ir_analyze_instruction_wasm_memory_size(ira, (Stage1ZirInstWasmMemorySize *)instruction);
25518 case Stage1ZirInstIdWasmMemoryGrow:
25519 return ir_analyze_instruction_wasm_memory_grow(ira, (Stage1ZirInstWasmMemoryGrow *)instruction);
25520 case Stage1ZirInstIdSrc:
25521 return ir_analyze_instruction_src(ira, (Stage1ZirInstSrc *)instruction);
25522 case Stage1ZirInstIdPrefetch:
25523 return ir_analyze_instruction_prefetch(ira, (Stage1ZirInstPrefetch *)instruction);
25524 case Stage1ZirInstIdAddrSpaceCast:
25525 return ir_analyze_instruction_addrspace_cast(ira, (Stage1ZirInstAddrSpaceCast *)instruction);
25526 }
25527 zig_unreachable();
25528}
25529
25530// This function attempts to evaluate stage1 ZIR code while doing type checking and other analysis.
25531// It emits to a new Stage1Air which is partially evaluated IR code.
25532ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *stage1_zir, Stage1Air *stage1_air,
25533 size_t *backward_branch_count, size_t *backward_branch_quota,
25534 ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr, ZigFn *fn)
25535{
25536 assert(stage1_zir->first_err_trace_msg == nullptr);
25537 assert(expected_type == nullptr || !type_is_invalid(expected_type));
25538
25539 IrAnalyze *ira = heap::c_allocator.create<IrAnalyze>();
25540 ira->fn = fn;
25541 ira->backward_branch_count = backward_branch_count;
25542 ira->backward_branch_quota = backward_branch_quota;
25543 ira->ref_count = 1;
25544 ira->codegen = codegen;
25545
25546 ira->explicit_return_type = expected_type;
25547 ira->explicit_return_type_source_node = expected_type_source_node;
25548
25549 ira->zir = stage1_zir;
25550
25551 ira->new_irb.codegen = codegen;
25552 ira->new_irb.exec = stage1_air;
25553
25554 Stage1ZirBasicBlock *old_entry_bb = ira->zir->basic_block_list.at(0);
25555 Stage1AirBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb, nullptr);
25556 ira->new_irb.current_basic_block = new_entry_bb;
25557 ira->old_bb_index = 0;
25558
25559 ir_start_bb(ira, old_entry_bb, nullptr);
25560
25561 if (result_ptr != nullptr) {
25562 assert(result_ptr->type->id == ZigTypeIdPointer);
25563 Stage1AirInstConst *const_inst = ir_create_inst_noval<Stage1AirInstConst>(
25564 &ira->new_irb, stage1_air->begin_scope, stage1_air->source_node);
25565 const_inst->base.value = result_ptr;
25566 ira->return_ptr = &const_inst->base;
25567 } else {
25568 assert(stage1_air->begin_scope != nullptr);
25569 assert(stage1_air->source_node != nullptr);
25570 ira->return_ptr = ir_build_return_ptr(ira, stage1_air->begin_scope, stage1_air->source_node,
25571 get_pointer_to_type(codegen, expected_type, false));
25572 }
25573
25574 while (ira->old_bb_index < ira->zir->basic_block_list.length) {
25575 Stage1ZirInst *old_instruction = ira->zir_current_basic_block->instruction_list.at(ira->instruction_index);
25576
25577 if (old_instruction->ref_count == 0 && !ir_inst_src_has_side_effects(old_instruction)) {
25578 ira->instruction_index += 1;
25579 continue;
25580 }
25581
25582 if (ira->codegen->verbose_ir) {
25583 fprintf(stderr, "~ ");
25584 old_instruction->src();
25585 fprintf(stderr, "~ ");
25586 ir_print_inst_src(codegen, stderr, old_instruction, 0);
25587 }
25588 ira->suspend_source_instr = old_instruction;
25589 Stage1AirInst *new_instruction = ir_analyze_instruction_base(ira, old_instruction);
25590 if (new_instruction != nullptr) {
25591 src_assert(new_instruction->value->type != nullptr || new_instruction->value->type != nullptr, old_instruction->source_node);
25592 old_instruction->child = new_instruction;
25593
25594 if (type_is_invalid(new_instruction->value->type)) {
25595 if (ira->codegen->verbose_ir) {
25596 fprintf(stderr, "-> (invalid)");
25597 }
25598
25599 if (stage1_air->first_err_trace_msg != nullptr) {
25600 ira->codegen->trace_err = stage1_air->first_err_trace_msg;
25601 } else {
25602 stage1_air->first_err_trace_msg = ira->codegen->trace_err;
25603 }
25604 return ira->codegen->builtin_types.entry_invalid;
25605 } else if (ira->codegen->verbose_ir) {
25606 fprintf(stderr, "-> ");
25607 if (new_instruction->value->type->id == ZigTypeIdUnreachable) {
25608 fprintf(stderr, "(noreturn)\n");
25609 } else {
25610 ir_print_inst_gen(codegen, stderr, new_instruction, 0);
25611 }
25612 }
25613
25614 // unreachable instructions do their own control flow.
25615 if (new_instruction->value->type->id == ZigTypeIdUnreachable)
25616 continue;
25617 } else {
25618 if (ira->codegen->verbose_ir) {
25619 fprintf(stderr, "-> (null");
25620 }
25621 }
25622
25623 ira->instruction_index += 1;
25624 }
25625
25626 ZigType *res_type;
25627 if (stage1_air->first_err_trace_msg != nullptr) {
25628 codegen->trace_err = stage1_air->first_err_trace_msg;
25629 res_type = ira->codegen->builtin_types.entry_invalid;
25630 } else if (ira->src_implicit_return_type_list.length == 0) {
25631 res_type = codegen->builtin_types.entry_unreachable;
25632 } else {
25633 res_type = ir_resolve_peer_types(ira, expected_type_source_node, expected_type, ira->src_implicit_return_type_list.items,
25634 ira->src_implicit_return_type_list.length);
25635 }
25636
25637 // It is now safe to free Pass 1 IR instructions.
25638 ira_deref(ira);
25639
25640 return res_type;
25641}
25642
25643bool ir_inst_gen_has_side_effects(Stage1AirInst *instruction) {
25644 switch (instruction->id) {
25645 case Stage1AirInstIdInvalid:
25646 zig_unreachable();
25647 case Stage1AirInstIdBr:
25648 case Stage1AirInstIdCondBr:
25649 case Stage1AirInstIdSwitchBr:
25650 case Stage1AirInstIdDeclVar:
25651 case Stage1AirInstIdStorePtr:
25652 case Stage1AirInstIdVectorStoreElem:
25653 case Stage1AirInstIdCall:
25654 case Stage1AirInstIdReturn:
25655 case Stage1AirInstIdUnreachable:
25656 case Stage1AirInstIdFence:
25657 case Stage1AirInstIdMemset:
25658 case Stage1AirInstIdMemcpy:
25659 case Stage1AirInstIdBreakpoint:
25660 case Stage1AirInstIdOverflowOp: // TODO when we support multiple returns this can be side effect free
25661 case Stage1AirInstIdPanic:
25662 case Stage1AirInstIdSaveErrRetAddr:
25663 case Stage1AirInstIdAtomicRmw:
25664 case Stage1AirInstIdAtomicStore:
25665 case Stage1AirInstIdCmpxchg:
25666 case Stage1AirInstIdAssertZero:
25667 case Stage1AirInstIdAssertNonNull:
25668 case Stage1AirInstIdPtrOfArrayToSlice:
25669 case Stage1AirInstIdSlice:
25670 case Stage1AirInstIdOptionalWrap:
25671 case Stage1AirInstIdVectorToArray:
25672 case Stage1AirInstIdSuspendBegin:
25673 case Stage1AirInstIdSuspendFinish:
25674 case Stage1AirInstIdResume:
25675 case Stage1AirInstIdAwait:
25676 case Stage1AirInstIdSpillBegin:
25677 case Stage1AirInstIdWasmMemoryGrow:
25678 case Stage1AirInstIdExtern:
25679 case Stage1AirInstIdPrefetch:
25680 return true;
25681
25682 case Stage1AirInstIdPhi:
25683 case Stage1AirInstIdBinOp:
25684 case Stage1AirInstIdConst:
25685 case Stage1AirInstIdCast:
25686 case Stage1AirInstIdElemPtr:
25687 case Stage1AirInstIdVarPtr:
25688 case Stage1AirInstIdReturnPtr:
25689 case Stage1AirInstIdStructFieldPtr:
25690 case Stage1AirInstIdTestNonNull:
25691 case Stage1AirInstIdClz:
25692 case Stage1AirInstIdCtz:
25693 case Stage1AirInstIdPopCount:
25694 case Stage1AirInstIdBswap:
25695 case Stage1AirInstIdBitReverse:
25696 case Stage1AirInstIdUnionTag:
25697 case Stage1AirInstIdTruncate:
25698 case Stage1AirInstIdShuffleVector:
25699 case Stage1AirInstIdSelect:
25700 case Stage1AirInstIdSplat:
25701 case Stage1AirInstIdBoolNot:
25702 case Stage1AirInstIdReturnAddress:
25703 case Stage1AirInstIdFrameAddress:
25704 case Stage1AirInstIdFrameHandle:
25705 case Stage1AirInstIdFrameSize:
25706 case Stage1AirInstIdTestErr:
25707 case Stage1AirInstIdPtrCast:
25708 case Stage1AirInstIdBitCast:
25709 case Stage1AirInstIdWidenOrShorten:
25710 case Stage1AirInstIdPtrToInt:
25711 case Stage1AirInstIdIntToPtr:
25712 case Stage1AirInstIdIntToEnum:
25713 case Stage1AirInstIdIntToErr:
25714 case Stage1AirInstIdErrToInt:
25715 case Stage1AirInstIdErrName:
25716 case Stage1AirInstIdTagName:
25717 case Stage1AirInstIdFieldParentPtr:
25718 case Stage1AirInstIdAlignCast:
25719 case Stage1AirInstIdErrorReturnTrace:
25720 case Stage1AirInstIdFloatOp:
25721 case Stage1AirInstIdMulAdd:
25722 case Stage1AirInstIdAtomicLoad:
25723 case Stage1AirInstIdArrayToVector:
25724 case Stage1AirInstIdAlloca:
25725 case Stage1AirInstIdSpillEnd:
25726 case Stage1AirInstIdVectorExtractElem:
25727 case Stage1AirInstIdBinaryNot:
25728 case Stage1AirInstIdNegation:
25729 case Stage1AirInstIdWasmMemorySize:
25730 case Stage1AirInstIdReduce:
25731 return false;
25732
25733 case Stage1AirInstIdAsm:
25734 {
25735 Stage1AirInstAsm *asm_instruction = (Stage1AirInstAsm *)instruction;
25736 return asm_instruction->has_side_effects;
25737 }
25738 case Stage1AirInstIdUnwrapErrPayload:
25739 {
25740 Stage1AirInstUnwrapErrPayload *unwrap_err_payload_instruction =
25741 (Stage1AirInstUnwrapErrPayload *)instruction;
25742 return unwrap_err_payload_instruction->safety_check_on ||
25743 unwrap_err_payload_instruction->initializing;
25744 }
25745 case Stage1AirInstIdUnwrapErrCode:
25746 return reinterpret_cast<Stage1AirInstUnwrapErrCode *>(instruction)->initializing;
25747 case Stage1AirInstIdUnionFieldPtr:
25748 return reinterpret_cast<Stage1AirInstUnionFieldPtr *>(instruction)->initializing;
25749 case Stage1AirInstIdOptionalUnwrapPtr:
25750 return reinterpret_cast<Stage1AirInstOptionalUnwrapPtr *>(instruction)->initializing;
25751 case Stage1AirInstIdErrWrapPayload:
25752 return reinterpret_cast<Stage1AirInstErrWrapPayload *>(instruction)->result_loc != nullptr;
25753 case Stage1AirInstIdErrWrapCode:
25754 return reinterpret_cast<Stage1AirInstErrWrapCode *>(instruction)->result_loc != nullptr;
25755 case Stage1AirInstIdLoadPtr:
25756 return reinterpret_cast<Stage1AirInstLoadPtr *>(instruction)->result_loc != nullptr;
25757 case Stage1AirInstIdRef:
25758 return reinterpret_cast<Stage1AirInstRef *>(instruction)->result_loc != nullptr;
25759 }
25760 zig_unreachable();
25761}
25762
25763bool ir_inst_src_has_side_effects(Stage1ZirInst *instruction) {
25764 switch (instruction->id) {
25765 case Stage1ZirInstIdInvalid:
25766 zig_unreachable();
25767 case Stage1ZirInstIdBr:
25768 case Stage1ZirInstIdCondBr:
25769 case Stage1ZirInstIdSwitchBr:
25770 case Stage1ZirInstIdDeclVar:
25771 case Stage1ZirInstIdStorePtr:
25772 case Stage1ZirInstIdCallExtra:
25773 case Stage1ZirInstIdAsyncCallExtra:
25774 case Stage1ZirInstIdCall:
25775 case Stage1ZirInstIdCallArgs:
25776 case Stage1ZirInstIdReturn:
25777 case Stage1ZirInstIdUnreachable:
25778 case Stage1ZirInstIdSetCold:
25779 case Stage1ZirInstIdSetRuntimeSafety:
25780 case Stage1ZirInstIdSetFloatMode:
25781 case Stage1ZirInstIdImport:
25782 case Stage1ZirInstIdCompileErr:
25783 case Stage1ZirInstIdCompileLog:
25784 case Stage1ZirInstIdCImport:
25785 case Stage1ZirInstIdCInclude:
25786 case Stage1ZirInstIdCDefine:
25787 case Stage1ZirInstIdCUndef:
25788 case Stage1ZirInstIdFence:
25789 case Stage1ZirInstIdMemset:
25790 case Stage1ZirInstIdMemcpy:
25791 case Stage1ZirInstIdBreakpoint:
25792 case Stage1ZirInstIdOverflowOp: // TODO when we support multiple returns this can be side effect free
25793 case Stage1ZirInstIdCheckSwitchProngsUnderNo:
25794 case Stage1ZirInstIdCheckSwitchProngsUnderYes:
25795 case Stage1ZirInstIdCheckStatementIsVoid:
25796 case Stage1ZirInstIdCheckRuntimeScope:
25797 case Stage1ZirInstIdPanic:
25798 case Stage1ZirInstIdSetEvalBranchQuota:
25799 case Stage1ZirInstIdPtrType:
25800 case Stage1ZirInstIdPtrTypeSimple:
25801 case Stage1ZirInstIdPtrTypeSimpleConst:
25802 case Stage1ZirInstIdSetAlignStack:
25803 case Stage1ZirInstIdExport:
25804 case Stage1ZirInstIdExtern:
25805 case Stage1ZirInstIdSaveErrRetAddr:
25806 case Stage1ZirInstIdAddImplicitReturnType:
25807 case Stage1ZirInstIdAtomicRmw:
25808 case Stage1ZirInstIdAtomicStore:
25809 case Stage1ZirInstIdCmpxchg:
25810 case Stage1ZirInstIdUndeclaredIdent:
25811 case Stage1ZirInstIdEndExpr:
25812 case Stage1ZirInstIdResetResult:
25813 case Stage1ZirInstIdSuspendBegin:
25814 case Stage1ZirInstIdSuspendFinish:
25815 case Stage1ZirInstIdResume:
25816 case Stage1ZirInstIdAwait:
25817 case Stage1ZirInstIdSpillBegin:
25818 case Stage1ZirInstIdWasmMemoryGrow:
25819 case Stage1ZirInstIdPrefetch:
25820 return true;
25821
25822 case Stage1ZirInstIdPhi:
25823 case Stage1ZirInstIdUnOp:
25824 case Stage1ZirInstIdBinOp:
25825 case Stage1ZirInstIdMergeErrSets:
25826 case Stage1ZirInstIdLoadPtr:
25827 case Stage1ZirInstIdConst:
25828 case Stage1ZirInstIdContainerInitList:
25829 case Stage1ZirInstIdContainerInitFields:
25830 case Stage1ZirInstIdUnionInitNamedField:
25831 case Stage1ZirInstIdFieldPtr:
25832 case Stage1ZirInstIdElemPtr:
25833 case Stage1ZirInstIdVarPtr:
25834 case Stage1ZirInstIdTypeOf:
25835 case Stage1ZirInstIdArrayType:
25836 case Stage1ZirInstIdSliceType:
25837 case Stage1ZirInstIdAnyFrameType:
25838 case Stage1ZirInstIdSizeOf:
25839 case Stage1ZirInstIdTestNonNull:
25840 case Stage1ZirInstIdOptionalUnwrapPtr:
25841 case Stage1ZirInstIdClz:
25842 case Stage1ZirInstIdCtz:
25843 case Stage1ZirInstIdPopCount:
25844 case Stage1ZirInstIdBswap:
25845 case Stage1ZirInstIdBitReverse:
25846 case Stage1ZirInstIdSwitchVar:
25847 case Stage1ZirInstIdSwitchElseVar:
25848 case Stage1ZirInstIdSwitchTarget:
25849 case Stage1ZirInstIdRef:
25850 case Stage1ZirInstIdEmbedFile:
25851 case Stage1ZirInstIdTruncate:
25852 case Stage1ZirInstIdVectorType:
25853 case Stage1ZirInstIdShuffleVector:
25854 case Stage1ZirInstIdSelect:
25855 case Stage1ZirInstIdSplat:
25856 case Stage1ZirInstIdBoolNot:
25857 case Stage1ZirInstIdSlice:
25858 case Stage1ZirInstIdAlignOf:
25859 case Stage1ZirInstIdReturnAddress:
25860 case Stage1ZirInstIdFrameAddress:
25861 case Stage1ZirInstIdFrameHandle:
25862 case Stage1ZirInstIdFrameType:
25863 case Stage1ZirInstIdFrameSize:
25864 case Stage1ZirInstIdTestErr:
25865 case Stage1ZirInstIdFnProto:
25866 case Stage1ZirInstIdTestComptime:
25867 case Stage1ZirInstIdPtrCast:
25868 case Stage1ZirInstIdBitCast:
25869 case Stage1ZirInstIdPtrToInt:
25870 case Stage1ZirInstIdIntToPtr:
25871 case Stage1ZirInstIdIntToEnum:
25872 case Stage1ZirInstIdIntToErr:
25873 case Stage1ZirInstIdErrToInt:
25874 case Stage1ZirInstIdDeclRef:
25875 case Stage1ZirInstIdErrName:
25876 case Stage1ZirInstIdTypeName:
25877 case Stage1ZirInstIdTagName:
25878 case Stage1ZirInstIdFieldParentPtr:
25879 case Stage1ZirInstIdOffsetOf:
25880 case Stage1ZirInstIdBitOffsetOf:
25881 case Stage1ZirInstIdTypeInfo:
25882 case Stage1ZirInstIdType:
25883 case Stage1ZirInstIdHasField:
25884 case Stage1ZirInstIdAlignCast:
25885 case Stage1ZirInstIdImplicitCast:
25886 case Stage1ZirInstIdResolveResult:
25887 case Stage1ZirInstIdArgTypeAllowVarFalse:
25888 case Stage1ZirInstIdArgTypeAllowVarTrue:
25889 case Stage1ZirInstIdErrorReturnTrace:
25890 case Stage1ZirInstIdErrorUnion:
25891 case Stage1ZirInstIdFloatOp:
25892 case Stage1ZirInstIdMulAdd:
25893 case Stage1ZirInstIdAtomicLoad:
25894 case Stage1ZirInstIdIntCast:
25895 case Stage1ZirInstIdFloatCast:
25896 case Stage1ZirInstIdErrSetCast:
25897 case Stage1ZirInstIdIntToFloat:
25898 case Stage1ZirInstIdFloatToInt:
25899 case Stage1ZirInstIdBoolToInt:
25900 case Stage1ZirInstIdEnumToInt:
25901 case Stage1ZirInstIdHasDecl:
25902 case Stage1ZirInstIdAlloca:
25903 case Stage1ZirInstIdSpillEnd:
25904 case Stage1ZirInstIdWasmMemorySize:
25905 case Stage1ZirInstIdSrc:
25906 case Stage1ZirInstIdReduce:
25907 case Stage1ZirInstIdAddrSpaceCast:
25908 return false;
25909
25910 case Stage1ZirInstIdAsm:
25911 {
25912 Stage1ZirInstAsm *asm_instruction = (Stage1ZirInstAsm *)instruction;
25913 return asm_instruction->has_side_effects;
25914 }
25915
25916 case Stage1ZirInstIdUnwrapErrPayload:
25917 {
25918 Stage1ZirInstUnwrapErrPayload *unwrap_err_payload_instruction =
25919 (Stage1ZirInstUnwrapErrPayload *)instruction;
25920 return unwrap_err_payload_instruction->safety_check_on ||
25921 unwrap_err_payload_instruction->initializing;
25922 }
25923 case Stage1ZirInstIdUnwrapErrCode:
25924 return reinterpret_cast<Stage1ZirInstUnwrapErrCode *>(instruction)->initializing;
25925 }
25926 zig_unreachable();
25927}
25928
25929static ZigType *ir_resolve_lazy_fn_type(IrAnalyze *ira, AstNode *source_node, LazyValueFnType *lazy_fn_type) {
25930 Error err;
25931 AstNode *proto_node = lazy_fn_type->proto_node;
25932
25933 FnTypeId fn_type_id = {0};
25934 init_fn_type_id(&fn_type_id, proto_node, lazy_fn_type->cc, proto_node->data.fn_proto.params.length);
25935
25936 if (proto_node->data.fn_proto.callconv_expr != nullptr) {
25937 if ((err = emit_error_unless_callconv_allowed_for_target(ira->codegen, proto_node->data.fn_proto.callconv_expr, lazy_fn_type->cc)))
25938 return nullptr;
25939 }
25940
25941 for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) {
25942 AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index);
25943 assert(param_node->type == NodeTypeParamDecl);
25944
25945 bool param_is_var_args = param_node->data.param_decl.is_var_args;
25946 if (param_is_var_args) {
25947 if (fn_type_id.cc == CallingConventionC) {
25948 fn_type_id.param_count = fn_type_id.next_param_index;
25949 break;
25950 } else {
25951 ir_add_error_node(ira, param_node,
25952 buf_sprintf("var args only allowed in functions with C calling convention"));
25953 return nullptr;
25954 }
25955 }
25956 FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
25957 param_info->is_noalias = param_node->data.param_decl.is_noalias;
25958
25959 if (lazy_fn_type->param_types[fn_type_id.next_param_index] == nullptr) {
25960 param_info->type = nullptr;
25961 return get_generic_fn_type(ira->codegen, &fn_type_id);
25962 } else {
25963 Stage1AirInst *param_type_inst = lazy_fn_type->param_types[fn_type_id.next_param_index];
25964 ZigType *param_type = ir_resolve_type(ira, param_type_inst);
25965 if (type_is_invalid(param_type))
25966 return nullptr;
25967
25968 if(!is_valid_param_type(param_type)){
25969 if(param_type->id == ZigTypeIdOpaque){
25970 ir_add_error(ira, param_type_inst,
25971 buf_sprintf("parameter of opaque type '%s' not allowed", buf_ptr(&param_type->name)));
25972 } else {
25973 ir_add_error(ira, param_type_inst,
25974 buf_sprintf("parameter of type '%s' not allowed", buf_ptr(&param_type->name)));
25975 }
25976
25977 return nullptr;
25978 }
25979
25980 switch (type_requires_comptime(ira->codegen, param_type)) {
25981 case ReqCompTimeYes:
25982 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
25983 ir_add_error(ira, param_type_inst,
25984 buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
25985 buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
25986 return nullptr;
25987 }
25988 param_info->type = param_type;
25989 fn_type_id.next_param_index += 1;
25990 return get_generic_fn_type(ira->codegen, &fn_type_id);
25991 case ReqCompTimeInvalid:
25992 return nullptr;
25993 case ReqCompTimeNo:
25994 break;
25995 }
25996 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
25997 bool has_bits;
25998 if ((err = type_has_bits2(ira->codegen, param_type, &has_bits)))
25999 return nullptr;
26000 if (!has_bits) {
26001 ir_add_error(ira, param_type_inst,
26002 buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'",
26003 buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
26004 return nullptr;
26005 }
26006 }
26007 param_info->type = param_type;
26008 }
26009 }
26010
26011 if (lazy_fn_type->align_inst != nullptr) {
26012 if (!ir_resolve_align(ira, lazy_fn_type->align_inst, nullptr, &fn_type_id.alignment))
26013 return nullptr;
26014 }
26015
26016 fn_type_id.return_type = ir_resolve_type(ira, lazy_fn_type->return_type);
26017 if (type_is_invalid(fn_type_id.return_type))
26018 return nullptr;
26019 if (fn_type_id.return_type->id == ZigTypeIdOpaque) {
26020 ir_add_error_node(ira, lazy_fn_type->return_type->source_node,
26021 buf_create_from_str("return type cannot be opaque"));
26022 return nullptr;
26023 }
26024
26025 return get_fn_type(ira->codegen, &fn_type_id);
26026}
26027
26028static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
26029 Error err;
26030 if (val->special != ConstValSpecialLazy)
26031 return ErrorNone;
26032 switch (val->data.x_lazy->id) {
26033 case LazyValueIdInvalid:
26034 zig_unreachable();
26035 case LazyValueIdTypeInfoDecls: {
26036 LazyValueTypeInfoDecls *type_info_decls = reinterpret_cast<LazyValueTypeInfoDecls *>(val->data.x_lazy);
26037 IrAnalyze *ira = type_info_decls->ira;
26038
26039 if ((err = ir_make_type_info_decls(ira, type_info_decls->source_node, val, type_info_decls->decls_scope, true)))
26040 {
26041 return err;
26042 };
26043
26044 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
26045 return ErrorNone;
26046 }
26047 case LazyValueIdAlignOf: {
26048 LazyValueAlignOf *lazy_align_of = reinterpret_cast<LazyValueAlignOf *>(val->data.x_lazy);
26049 IrAnalyze *ira = lazy_align_of->ira;
26050
26051 if (lazy_align_of->target_type->value->special == ConstValSpecialStatic) {
26052 switch (lazy_align_of->target_type->value->data.x_type->id) {
26053 case ZigTypeIdInvalid:
26054 zig_unreachable();
26055 case ZigTypeIdMetaType:
26056 case ZigTypeIdUnreachable:
26057 case ZigTypeIdComptimeFloat:
26058 case ZigTypeIdComptimeInt:
26059 case ZigTypeIdEnumLiteral:
26060 case ZigTypeIdUndefined:
26061 case ZigTypeIdNull:
26062 case ZigTypeIdBoundFn:
26063 case ZigTypeIdVoid:
26064 case ZigTypeIdOpaque:
26065 ir_add_error_node(ira, source_node,
26066 buf_sprintf("no align available for type '%s'",
26067 buf_ptr(&lazy_align_of->target_type->value->data.x_type->name)));
26068 return ErrorSemanticAnalyzeFail;
26069 case ZigTypeIdBool:
26070 case ZigTypeIdInt:
26071 case ZigTypeIdFloat:
26072 case ZigTypeIdPointer:
26073 case ZigTypeIdArray:
26074 case ZigTypeIdStruct:
26075 case ZigTypeIdOptional:
26076 case ZigTypeIdErrorUnion:
26077 case ZigTypeIdErrorSet:
26078 case ZigTypeIdEnum:
26079 case ZigTypeIdUnion:
26080 case ZigTypeIdFn:
26081 case ZigTypeIdVector:
26082 case ZigTypeIdFnFrame:
26083 case ZigTypeIdAnyFrame:
26084 break;
26085 }
26086 }
26087
26088 uint32_t align_in_bytes;
26089 if ((err = type_val_resolve_abi_align(ira->codegen, source_node,
26090 lazy_align_of->target_type->value, &align_in_bytes)))
26091 {
26092 return err;
26093 }
26094
26095 val->special = ConstValSpecialStatic;
26096 assert(val->type->id == ZigTypeIdComptimeInt || val->type->id == ZigTypeIdInt);
26097 bigint_init_unsigned(&val->data.x_bigint, align_in_bytes);
26098
26099 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
26100 return ErrorNone;
26101 }
26102 case LazyValueIdSizeOf: {
26103 LazyValueSizeOf *lazy_size_of = reinterpret_cast<LazyValueSizeOf *>(val->data.x_lazy);
26104 IrAnalyze *ira = lazy_size_of->ira;
26105
26106 if (lazy_size_of->target_type->value->special == ConstValSpecialStatic) {
26107 switch (lazy_size_of->target_type->value->data.x_type->id) {
26108 case ZigTypeIdInvalid: // handled above
26109 zig_unreachable();
26110 case ZigTypeIdUnreachable:
26111 case ZigTypeIdUndefined:
26112 case ZigTypeIdNull:
26113 case ZigTypeIdBoundFn:
26114 case ZigTypeIdOpaque:
26115 ir_add_error_node(ira, lazy_size_of->target_type->source_node,
26116 buf_sprintf("no size available for type '%s'",
26117 buf_ptr(&lazy_size_of->target_type->value->data.x_type->name)));
26118 return ErrorSemanticAnalyzeFail;
26119 case ZigTypeIdMetaType:
26120 case ZigTypeIdEnumLiteral:
26121 case ZigTypeIdComptimeFloat:
26122 case ZigTypeIdComptimeInt:
26123 case ZigTypeIdVoid:
26124 case ZigTypeIdBool:
26125 case ZigTypeIdInt:
26126 case ZigTypeIdFloat:
26127 case ZigTypeIdPointer:
26128 case ZigTypeIdArray:
26129 case ZigTypeIdStruct:
26130 case ZigTypeIdOptional:
26131 case ZigTypeIdErrorUnion:
26132 case ZigTypeIdErrorSet:
26133 case ZigTypeIdEnum:
26134 case ZigTypeIdUnion:
26135 case ZigTypeIdFn:
26136 case ZigTypeIdVector:
26137 case ZigTypeIdFnFrame:
26138 case ZigTypeIdAnyFrame:
26139 break;
26140 }
26141 }
26142
26143 size_t abi_size;
26144 size_t size_in_bits;
26145 if ((err = type_val_resolve_abi_size(ira->codegen, source_node, lazy_size_of->target_type->value,
26146 &abi_size, &size_in_bits)))
26147 {
26148 return err;
26149 }
26150
26151 val->special = ConstValSpecialStatic;
26152 assert(val->type->id == ZigTypeIdComptimeInt || val->type->id == ZigTypeIdInt);
26153 if (lazy_size_of->bit_size)
26154 bigint_init_unsigned(&val->data.x_bigint, size_in_bits);
26155 else
26156 bigint_init_unsigned(&val->data.x_bigint, abi_size);
26157
26158 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
26159 return ErrorNone;
26160 }
26161 case LazyValueIdSliceType: {
26162 LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(val->data.x_lazy);
26163 IrAnalyze *ira = lazy_slice_type->ira;
26164
26165 ZigType *elem_type = ir_resolve_type(ira, lazy_slice_type->elem_type);
26166 if (type_is_invalid(elem_type))
26167 return ErrorSemanticAnalyzeFail;
26168
26169 ZigValue *sentinel_val;
26170 if (lazy_slice_type->sentinel != nullptr) {
26171 if (type_is_invalid(lazy_slice_type->sentinel->value->type))
26172 return ErrorSemanticAnalyzeFail;
26173 Stage1AirInst *sentinel = ir_implicit_cast(ira, lazy_slice_type->sentinel, elem_type);
26174 if (type_is_invalid(sentinel->value->type))
26175 return ErrorSemanticAnalyzeFail;
26176 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
26177 if (sentinel_val == nullptr)
26178 return ErrorSemanticAnalyzeFail;
26179 } else {
26180 sentinel_val = nullptr;
26181 }
26182
26183 uint32_t align_bytes = 0;
26184 if (lazy_slice_type->align_inst != nullptr) {
26185 if (!ir_resolve_align(ira, lazy_slice_type->align_inst, elem_type, &align_bytes))
26186 return ErrorSemanticAnalyzeFail;
26187 }
26188
26189 switch (elem_type->id) {
26190 case ZigTypeIdInvalid: // handled above
26191 zig_unreachable();
26192 case ZigTypeIdUnreachable:
26193 case ZigTypeIdUndefined:
26194 case ZigTypeIdNull:
26195 case ZigTypeIdOpaque:
26196 ir_add_error_node(ira, lazy_slice_type->elem_type->source_node,
26197 buf_sprintf("slice of type '%s' not allowed", buf_ptr(&elem_type->name)));
26198 return ErrorSemanticAnalyzeFail;
26199 case ZigTypeIdMetaType:
26200 case ZigTypeIdVoid:
26201 case ZigTypeIdBool:
26202 case ZigTypeIdInt:
26203 case ZigTypeIdFloat:
26204 case ZigTypeIdPointer:
26205 case ZigTypeIdArray:
26206 case ZigTypeIdStruct:
26207 case ZigTypeIdComptimeFloat:
26208 case ZigTypeIdComptimeInt:
26209 case ZigTypeIdEnumLiteral:
26210 case ZigTypeIdOptional:
26211 case ZigTypeIdErrorUnion:
26212 case ZigTypeIdErrorSet:
26213 case ZigTypeIdEnum:
26214 case ZigTypeIdUnion:
26215 case ZigTypeIdFn:
26216 case ZigTypeIdBoundFn:
26217 case ZigTypeIdVector:
26218 case ZigTypeIdFnFrame:
26219 case ZigTypeIdAnyFrame:
26220 break;
26221 }
26222
26223 ResolveStatus needed_status = (align_bytes == 0) ?
26224 ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown;
26225 if ((err = type_resolve(ira->codegen, elem_type, needed_status)))
26226 return err;
26227 ZigType *slice_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
26228 lazy_slice_type->is_const, lazy_slice_type->is_volatile,
26229 PtrLenUnknown,
26230 align_bytes,
26231 0, 0, lazy_slice_type->is_allowzero,
26232 VECTOR_INDEX_NONE, nullptr, sentinel_val);
26233 val->special = ConstValSpecialStatic;
26234 assert(val->type->id == ZigTypeIdMetaType);
26235 val->data.x_type = get_slice_type(ira->codegen, slice_ptr_type);
26236
26237 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
26238 return ErrorNone;
26239 }
26240 case LazyValueIdPtrType: {
26241 LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(val->data.x_lazy);
26242 IrAnalyze *ira = lazy_ptr_type->ira;
26243
26244 ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type);
26245 if (type_is_invalid(elem_type))
26246 return ErrorSemanticAnalyzeFail;
26247
26248 ZigValue *sentinel_val;
26249 if (lazy_ptr_type->sentinel != nullptr) {
26250 if (type_is_invalid(lazy_ptr_type->sentinel->value->type))
26251 return ErrorSemanticAnalyzeFail;
26252 Stage1AirInst *sentinel = ir_implicit_cast(ira, lazy_ptr_type->sentinel, elem_type);
26253 if (type_is_invalid(sentinel->value->type))
26254 return ErrorSemanticAnalyzeFail;
26255 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
26256 if (sentinel_val == nullptr)
26257 return ErrorSemanticAnalyzeFail;
26258 } else {
26259 sentinel_val = nullptr;
26260 }
26261
26262 uint32_t align_bytes = 0;
26263 if (lazy_ptr_type->align_inst != nullptr) {
26264 if (!ir_resolve_align(ira, lazy_ptr_type->align_inst, elem_type, &align_bytes))
26265 return ErrorSemanticAnalyzeFail;
26266 }
26267
26268 if (elem_type->id == ZigTypeIdUnreachable) {
26269 ir_add_error_node(ira, lazy_ptr_type->elem_type->source_node,
26270 buf_create_from_str("pointer to noreturn not allowed"));
26271 return ErrorSemanticAnalyzeFail;
26272 } else if (elem_type->id == ZigTypeIdOpaque && lazy_ptr_type->ptr_len == PtrLenUnknown) {
26273 ir_add_error_node(ira, lazy_ptr_type->elem_type->source_node,
26274 buf_create_from_str("unknown-length pointer to opaque"));
26275 return ErrorSemanticAnalyzeFail;
26276 } else if (lazy_ptr_type->ptr_len == PtrLenC) {
26277 bool ok_type;
26278 if ((err = type_allowed_in_extern(ira->codegen, elem_type, ExternPositionOther, &ok_type)))
26279 return err;
26280 if (!ok_type) {
26281 ir_add_error_node(ira, lazy_ptr_type->elem_type->source_node,
26282 buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'",
26283 buf_ptr(&elem_type->name)));
26284 return ErrorSemanticAnalyzeFail;
26285 } else if (elem_type->id == ZigTypeIdOpaque) {
26286 ir_add_error_node(ira, lazy_ptr_type->elem_type->source_node,
26287 buf_sprintf("C pointers cannot point to opaque types"));
26288 return ErrorSemanticAnalyzeFail;
26289 } else if (lazy_ptr_type->is_allowzero) {
26290 ir_add_error_node(ira, lazy_ptr_type->elem_type->source_node,
26291 buf_sprintf("C pointers always allow address zero"));
26292 return ErrorSemanticAnalyzeFail;
26293 }
26294 }
26295
26296 if (align_bytes != 0) {
26297 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusAlignmentKnown)))
26298 return err;
26299 if (!type_has_bits(ira->codegen, elem_type))
26300 align_bytes = 0;
26301 }
26302 bool allow_zero = lazy_ptr_type->is_allowzero || lazy_ptr_type->ptr_len == PtrLenC;
26303 assert(val->type->id == ZigTypeIdMetaType);
26304 val->data.x_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
26305 lazy_ptr_type->is_const, lazy_ptr_type->is_volatile, lazy_ptr_type->ptr_len, align_bytes,
26306 lazy_ptr_type->bit_offset_in_host, lazy_ptr_type->host_int_bytes,
26307 allow_zero, VECTOR_INDEX_NONE, nullptr, sentinel_val);
26308 val->special = ConstValSpecialStatic;
26309
26310 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
26311 return ErrorNone;
26312 }
26313 case LazyValueIdPtrTypeSimple: {
26314 LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(val->data.x_lazy);
26315 IrAnalyze *ira = lazy_ptr_type->ira;
26316
26317 ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type);
26318 if (type_is_invalid(elem_type))
26319 return ErrorSemanticAnalyzeFail;
26320
26321 if (elem_type->id == ZigTypeIdUnreachable) {
26322 ir_add_error_node(ira, lazy_ptr_type->elem_type->source_node,
26323 buf_create_from_str("pointer to noreturn not allowed"));
26324 return ErrorSemanticAnalyzeFail;
26325 }
26326
26327 assert(val->type->id == ZigTypeIdMetaType);
26328 val->data.x_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
26329 false, false, PtrLenSingle, 0,
26330 0, 0,
26331 false, VECTOR_INDEX_NONE, nullptr, nullptr);
26332 val->special = ConstValSpecialStatic;
26333
26334 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
26335 return ErrorNone;
26336 }
26337 case LazyValueIdPtrTypeSimpleConst: {
26338 LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(val->data.x_lazy);
26339 IrAnalyze *ira = lazy_ptr_type->ira;
26340
26341 ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type);
26342 if (type_is_invalid(elem_type))
26343 return ErrorSemanticAnalyzeFail;
26344
26345 if (elem_type->id == ZigTypeIdUnreachable) {
26346 ir_add_error_node(ira, lazy_ptr_type->elem_type->source_node,
26347 buf_create_from_str("pointer to noreturn not allowed"));
26348 return ErrorSemanticAnalyzeFail;
26349 }
26350
26351 assert(val->type->id == ZigTypeIdMetaType);
26352 val->data.x_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
26353 true, false, PtrLenSingle, 0,
26354 0, 0,
26355 false, VECTOR_INDEX_NONE, nullptr, nullptr);
26356 val->special = ConstValSpecialStatic;
26357
26358 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
26359 return ErrorNone;
26360 }
26361 case LazyValueIdArrayType: {
26362 LazyValueArrayType *lazy_array_type = reinterpret_cast<LazyValueArrayType *>(val->data.x_lazy);
26363 IrAnalyze *ira = lazy_array_type->ira;
26364
26365 ZigType *elem_type = ir_resolve_type(ira, lazy_array_type->elem_type);
26366 if (type_is_invalid(elem_type))
26367 return ErrorSemanticAnalyzeFail;
26368
26369 switch (elem_type->id) {
26370 case ZigTypeIdInvalid: // handled above
26371 zig_unreachable();
26372 case ZigTypeIdUnreachable:
26373 case ZigTypeIdUndefined:
26374 case ZigTypeIdNull:
26375 case ZigTypeIdOpaque:
26376 ir_add_error_node(ira, lazy_array_type->elem_type->source_node,
26377 buf_sprintf("array of type '%s' not allowed",
26378 buf_ptr(&elem_type->name)));
26379 return ErrorSemanticAnalyzeFail;
26380 case ZigTypeIdMetaType:
26381 case ZigTypeIdVoid:
26382 case ZigTypeIdBool:
26383 case ZigTypeIdInt:
26384 case ZigTypeIdFloat:
26385 case ZigTypeIdPointer:
26386 case ZigTypeIdArray:
26387 case ZigTypeIdStruct:
26388 case ZigTypeIdComptimeFloat:
26389 case ZigTypeIdComptimeInt:
26390 case ZigTypeIdEnumLiteral:
26391 case ZigTypeIdOptional:
26392 case ZigTypeIdErrorUnion:
26393 case ZigTypeIdErrorSet:
26394 case ZigTypeIdEnum:
26395 case ZigTypeIdUnion:
26396 case ZigTypeIdFn:
26397 case ZigTypeIdBoundFn:
26398 case ZigTypeIdVector:
26399 case ZigTypeIdFnFrame:
26400 case ZigTypeIdAnyFrame:
26401 break;
26402 }
26403
26404 // Avoid resolving the type if the total length is zero.
26405 // Matches the logic in get_array_type and in the lazy alignment
26406 // resolution routine.
26407 if (lazy_array_type->length + (lazy_array_type->sentinel != nullptr) != 0) {
26408 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
26409 return err;
26410 }
26411
26412 ZigValue *sentinel_val = nullptr;
26413 if (lazy_array_type->sentinel != nullptr) {
26414 if (type_is_invalid(lazy_array_type->sentinel->value->type))
26415 return ErrorSemanticAnalyzeFail;
26416 Stage1AirInst *sentinel = ir_implicit_cast(ira, lazy_array_type->sentinel, elem_type);
26417 if (type_is_invalid(sentinel->value->type))
26418 return ErrorSemanticAnalyzeFail;
26419 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
26420 if (sentinel_val == nullptr)
26421 return ErrorSemanticAnalyzeFail;
26422 }
26423
26424 assert(val->type->id == ZigTypeIdMetaType);
26425 val->data.x_type = get_array_type(ira->codegen, elem_type, lazy_array_type->length, sentinel_val);
26426 val->special = ConstValSpecialStatic;
26427
26428 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
26429 return ErrorNone;
26430 }
26431 case LazyValueIdOptType: {
26432 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(val->data.x_lazy);
26433 IrAnalyze *ira = lazy_opt_type->ira;
26434
26435 ZigType *payload_type = ir_resolve_type(ira, lazy_opt_type->payload_type);
26436 if (type_is_invalid(payload_type))
26437 return ErrorSemanticAnalyzeFail;
26438
26439 if (payload_type->id == ZigTypeIdOpaque || payload_type->id == ZigTypeIdUnreachable) {
26440 ir_add_error_node(ira, lazy_opt_type->payload_type->source_node,
26441 buf_sprintf("type '%s' cannot be optional", buf_ptr(&payload_type->name)));
26442 return ErrorSemanticAnalyzeFail;
26443 }
26444
26445 if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown)))
26446 return err;
26447
26448 assert(val->type->id == ZigTypeIdMetaType);
26449 val->data.x_type = get_optional_type(ira->codegen, payload_type);
26450 val->special = ConstValSpecialStatic;
26451
26452 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
26453 return ErrorNone;
26454 }
26455 case LazyValueIdFnType: {
26456 LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(val->data.x_lazy);
26457 IrAnalyze *ira = lazy_fn_type->ira;
26458 ZigType *fn_type = ir_resolve_lazy_fn_type(ira, source_node, lazy_fn_type);
26459 if (fn_type == nullptr)
26460 return ErrorSemanticAnalyzeFail;
26461 val->special = ConstValSpecialStatic;
26462 assert(val->type->id == ZigTypeIdMetaType);
26463 val->data.x_type = fn_type;
26464
26465 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
26466 return ErrorNone;
26467 }
26468 case LazyValueIdErrUnionType: {
26469 LazyValueErrUnionType *lazy_err_union_type =
26470 reinterpret_cast<LazyValueErrUnionType *>(val->data.x_lazy);
26471 IrAnalyze *ira = lazy_err_union_type->ira;
26472
26473 ZigType *err_set_type = ir_resolve_type(ira, lazy_err_union_type->err_set_type);
26474 if (type_is_invalid(err_set_type))
26475 return ErrorSemanticAnalyzeFail;
26476
26477 ZigType *payload_type = ir_resolve_type(ira, lazy_err_union_type->payload_type);
26478 if (type_is_invalid(payload_type))
26479 return ErrorSemanticAnalyzeFail;
26480
26481 if (err_set_type->id != ZigTypeIdErrorSet) {
26482 ir_add_error_node(ira, lazy_err_union_type->err_set_type->source_node,
26483 buf_sprintf("expected error set type, found type '%s'",
26484 buf_ptr(&err_set_type->name)));
26485 return ErrorSemanticAnalyzeFail;
26486 }
26487
26488 if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown)))
26489 return ErrorSemanticAnalyzeFail;
26490
26491 assert(val->type->id == ZigTypeIdMetaType);
26492 val->data.x_type = get_error_union_type(ira->codegen, err_set_type, payload_type);
26493 val->special = ConstValSpecialStatic;
26494
26495 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
26496 return ErrorNone;
26497 }
26498 }
26499 zig_unreachable();
26500}
26501
26502static Error ir_resolve_lazy_recurse_array(AstNode *source_node, ZigValue *val, size_t len) {
26503 Error err;
26504 switch (val->data.x_array.special) {
26505 case ConstArraySpecialUndef:
26506 case ConstArraySpecialBuf:
26507 return ErrorNone;
26508 case ConstArraySpecialNone:
26509 break;
26510 }
26511 ZigValue *elems = val->data.x_array.data.s_none.elements;
26512
26513 for (size_t i = 0; i < len; i += 1) {
26514 if ((err = ir_resolve_lazy_recurse(source_node, &elems[i])))
26515 return err;
26516 }
26517
26518 return ErrorNone;
26519}
26520
26521static Error ir_resolve_lazy_recurse(AstNode *source_node, ZigValue *val) {
26522 Error err;
26523 if ((err = ir_resolve_lazy_raw(source_node, val)))
26524 return err;
26525 assert(val->special != ConstValSpecialRuntime);
26526 assert(val->special != ConstValSpecialLazy);
26527 if (val->special != ConstValSpecialStatic)
26528 return ErrorNone;
26529 switch (val->type->id) {
26530 case ZigTypeIdOpaque:
26531 case ZigTypeIdEnum:
26532 case ZigTypeIdMetaType:
26533 case ZigTypeIdBool:
26534 case ZigTypeIdVoid:
26535 case ZigTypeIdComptimeFloat:
26536 case ZigTypeIdInt:
26537 case ZigTypeIdComptimeInt:
26538 case ZigTypeIdEnumLiteral:
26539 case ZigTypeIdErrorSet:
26540 case ZigTypeIdUndefined:
26541 case ZigTypeIdNull:
26542 case ZigTypeIdPointer:
26543 case ZigTypeIdFn:
26544 case ZigTypeIdAnyFrame:
26545 case ZigTypeIdBoundFn:
26546 case ZigTypeIdInvalid:
26547 case ZigTypeIdUnreachable:
26548 case ZigTypeIdFloat:
26549 return ErrorNone;
26550 case ZigTypeIdFnFrame:
26551 zig_panic("TODO: ir_resolve_lazy_recurse ZigTypeIdFnFrame");
26552 case ZigTypeIdUnion: {
26553 ConstUnionValue *union_val = &val->data.x_union;
26554 return ir_resolve_lazy_recurse(source_node, union_val->payload);
26555 }
26556 case ZigTypeIdVector:
26557 return ir_resolve_lazy_recurse_array(source_node, val, val->type->data.vector.len);
26558 case ZigTypeIdArray:
26559 return ir_resolve_lazy_recurse_array(source_node, val, val->type->data.array.len);
26560 case ZigTypeIdStruct:
26561 for (size_t i = 0; i < val->type->data.structure.src_field_count; i += 1) {
26562 ZigValue *field = val->data.x_struct.fields[i];
26563 if (val->type->data.structure.fields[i]->is_comptime) {
26564 // comptime struct fields do not need to be resolved because
26565 // they are not part of the value.
26566 continue;
26567 }
26568 if ((err = ir_resolve_lazy_recurse(source_node, field)))
26569 return err;
26570 }
26571 return ErrorNone;
26572 case ZigTypeIdOptional:
26573 if (get_src_ptr_type(val->type) != nullptr)
26574 return ErrorNone;
26575 if (val->data.x_optional == nullptr)
26576 return ErrorNone;
26577
26578 return ir_resolve_lazy_recurse(source_node, val->data.x_optional);
26579 case ZigTypeIdErrorUnion: {
26580 bool is_err = val->data.x_err_union.error_set->data.x_err_set != nullptr;
26581 if (is_err) {
26582 return ir_resolve_lazy_recurse(source_node, val->data.x_err_union.error_set);
26583 } else {
26584 return ir_resolve_lazy_recurse(source_node, val->data.x_err_union.payload);
26585 }
26586 }
26587 }
26588 zig_unreachable();
26589}
26590
26591Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val) {
26592 Error err;
26593 if ((err = ir_resolve_lazy_raw(source_node, val))) {
26594 return err;
26595 }
26596 if (type_is_invalid(val->type)) {
26597 return ErrorSemanticAnalyzeFail;
26598 }
26599 return ErrorNone;
26600}
26601
26602void Stage1AirInst::src() {
26603 Stage1AirInst *inst = this;
26604 if (inst->source_node != nullptr) {
26605 inst->source_node->src();
26606 } else {
26607 fprintf(stderr, "(null source node)\n");
26608 }
26609}
26610
26611void Stage1AirInst::dump() {
26612 Stage1AirInst *inst = this;
26613 inst->src();
26614 if (inst->scope == nullptr) {
26615 fprintf(stderr, "(null scope)\n");
26616 } else {
26617 ir_print_inst_gen(inst->scope->codegen, stderr, inst, 0);
26618 }
26619}
26620
26621void IrAnalyze::dump() {
26622 ir_print_gen(this->codegen, stderr, this->new_irb.exec, 0);
26623 if (this->new_irb.current_basic_block != nullptr) {
26624 fprintf(stderr, "Current basic block:\n");
26625 ir_print_basic_block_gen(this->codegen, stderr, this->new_irb.current_basic_block, 1);
26626 }
26627}
src/stage1/ir.hpp deleted-34
...@@ -1,34 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_IR_HPP
9#define ZIG_IR_HPP
10
11#include "all_types.hpp"
12
13Stage1AirInst *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn,
14 ZigType *var_type, const char *name_hint);
15
16Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
17 ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota,
18 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
19 Stage1Air *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef);
20
21Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val);
22
23ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *stage1_zir, Stage1Air *stage1_air,
24 size_t *backward_branch_count, size_t *backward_branch_quota,
25 ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr,
26 ZigFn *fn);
27
28bool ir_inst_gen_has_side_effects(Stage1AirInst *inst);
29
30struct IrAnalyze;
31ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val,
32 AstNode *source_node);
33
34#endif
src/stage1/ir_print.cpp deleted-3543
...@@ -1,3543 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "all_types.hpp"
9#include "analyze.hpp"
10#include "ir.hpp"
11#include "astgen.hpp"
12#include "ir_print.hpp"
13#include "os.hpp"
14
15static uint32_t hash_inst_src_ptr(Stage1ZirInst* instruction) {
16 return (uint32_t)(uintptr_t)instruction;
17}
18
19static uint32_t hash_inst_gen_ptr(Stage1AirInst* instruction) {
20 return (uint32_t)(uintptr_t)instruction;
21}
22
23static bool inst_src_ptr_eql(Stage1ZirInst* a, Stage1ZirInst* b) {
24 return a == b;
25}
26
27static bool inst_gen_ptr_eql(Stage1AirInst* a, Stage1AirInst* b) {
28 return a == b;
29}
30
31using InstSetSrc = HashMap<Stage1ZirInst*, uint8_t, hash_inst_src_ptr, inst_src_ptr_eql>;
32using InstSetGen = HashMap<Stage1AirInst*, uint8_t, hash_inst_gen_ptr, inst_gen_ptr_eql>;
33using InstListSrc = ZigList<Stage1ZirInst*>;
34using InstListGen = ZigList<Stage1AirInst*>;
35
36struct IrPrintSrc {
37 CodeGen *codegen;
38 FILE *f;
39 int indent;
40 int indent_size;
41};
42
43struct IrPrintGen {
44 CodeGen *codegen;
45 FILE *f;
46 int indent;
47 int indent_size;
48
49 // When printing pass 2 instructions referenced var instructions are not
50 // present in the instruction list. Thus we track which instructions
51 // are printed (per executable) and after each pass 2 instruction those
52 // var instructions are rendered in a trailing fashion.
53 InstSetGen printed;
54 InstListGen pending;
55};
56
57static void ir_print_other_inst_src(IrPrintSrc *irp, Stage1ZirInst *inst);
58static void ir_print_other_inst_gen(IrPrintGen *irp, Stage1AirInst *inst);
59
60static void ir_print_call_modifier(FILE *f, CallModifier modifier) {
61 switch (modifier) {
62 case CallModifierNone:
63 break;
64 case CallModifierNoSuspend:
65 fprintf(f, "nosuspend ");
66 break;
67 case CallModifierAsync:
68 fprintf(f, "async ");
69 break;
70 case CallModifierNeverTail:
71 fprintf(f, "notail ");
72 break;
73 case CallModifierNeverInline:
74 fprintf(f, "noinline ");
75 break;
76 case CallModifierAlwaysTail:
77 fprintf(f, "tail ");
78 break;
79 case CallModifierAlwaysInline:
80 fprintf(f, "inline ");
81 break;
82 case CallModifierCompileTime:
83 fprintf(f, "comptime ");
84 break;
85 case CallModifierBuiltin:
86 zig_unreachable();
87 }
88}
89
90const char* ir_inst_src_type_str(Stage1ZirInstId id) {
91 switch (id) {
92 case Stage1ZirInstIdInvalid:
93 return "SrcInvalid";
94 case Stage1ZirInstIdShuffleVector:
95 return "SrcShuffle";
96 case Stage1ZirInstIdSelect:
97 return "SrcSelect";
98 case Stage1ZirInstIdSplat:
99 return "SrcSplat";
100 case Stage1ZirInstIdDeclVar:
101 return "SrcDeclVar";
102 case Stage1ZirInstIdBr:
103 return "SrcBr";
104 case Stage1ZirInstIdCondBr:
105 return "SrcCondBr";
106 case Stage1ZirInstIdSwitchBr:
107 return "SrcSwitchBr";
108 case Stage1ZirInstIdSwitchVar:
109 return "SrcSwitchVar";
110 case Stage1ZirInstIdSwitchElseVar:
111 return "SrcSwitchElseVar";
112 case Stage1ZirInstIdSwitchTarget:
113 return "SrcSwitchTarget";
114 case Stage1ZirInstIdPhi:
115 return "SrcPhi";
116 case Stage1ZirInstIdUnOp:
117 return "SrcUnOp";
118 case Stage1ZirInstIdBinOp:
119 return "SrcBinOp";
120 case Stage1ZirInstIdMergeErrSets:
121 return "SrcMergeErrSets";
122 case Stage1ZirInstIdLoadPtr:
123 return "SrcLoadPtr";
124 case Stage1ZirInstIdStorePtr:
125 return "SrcStorePtr";
126 case Stage1ZirInstIdFieldPtr:
127 return "SrcFieldPtr";
128 case Stage1ZirInstIdElemPtr:
129 return "SrcElemPtr";
130 case Stage1ZirInstIdVarPtr:
131 return "SrcVarPtr";
132 case Stage1ZirInstIdCallExtra:
133 return "SrcCallExtra";
134 case Stage1ZirInstIdAsyncCallExtra:
135 return "SrcAsyncCallExtra";
136 case Stage1ZirInstIdCall:
137 return "SrcCall";
138 case Stage1ZirInstIdCallArgs:
139 return "SrcCallArgs";
140 case Stage1ZirInstIdConst:
141 return "SrcConst";
142 case Stage1ZirInstIdReturn:
143 return "SrcReturn";
144 case Stage1ZirInstIdContainerInitList:
145 return "SrcContainerInitList";
146 case Stage1ZirInstIdContainerInitFields:
147 return "SrcContainerInitFields";
148 case Stage1ZirInstIdUnreachable:
149 return "SrcUnreachable";
150 case Stage1ZirInstIdTypeOf:
151 return "SrcTypeOf";
152 case Stage1ZirInstIdSetCold:
153 return "SrcSetCold";
154 case Stage1ZirInstIdSetRuntimeSafety:
155 return "SrcSetRuntimeSafety";
156 case Stage1ZirInstIdSetFloatMode:
157 return "SrcSetFloatMode";
158 case Stage1ZirInstIdArrayType:
159 return "SrcArrayType";
160 case Stage1ZirInstIdAnyFrameType:
161 return "SrcAnyFrameType";
162 case Stage1ZirInstIdSliceType:
163 return "SrcSliceType";
164 case Stage1ZirInstIdAsm:
165 return "SrcAsm";
166 case Stage1ZirInstIdSizeOf:
167 return "SrcSizeOf";
168 case Stage1ZirInstIdTestNonNull:
169 return "SrcTestNonNull";
170 case Stage1ZirInstIdOptionalUnwrapPtr:
171 return "SrcOptionalUnwrapPtr";
172 case Stage1ZirInstIdClz:
173 return "SrcClz";
174 case Stage1ZirInstIdCtz:
175 return "SrcCtz";
176 case Stage1ZirInstIdPopCount:
177 return "SrcPopCount";
178 case Stage1ZirInstIdBswap:
179 return "SrcBswap";
180 case Stage1ZirInstIdBitReverse:
181 return "SrcBitReverse";
182 case Stage1ZirInstIdImport:
183 return "SrcImport";
184 case Stage1ZirInstIdCImport:
185 return "SrcCImport";
186 case Stage1ZirInstIdCInclude:
187 return "SrcCInclude";
188 case Stage1ZirInstIdCDefine:
189 return "SrcCDefine";
190 case Stage1ZirInstIdCUndef:
191 return "SrcCUndef";
192 case Stage1ZirInstIdRef:
193 return "SrcRef";
194 case Stage1ZirInstIdCompileErr:
195 return "SrcCompileErr";
196 case Stage1ZirInstIdCompileLog:
197 return "SrcCompileLog";
198 case Stage1ZirInstIdErrName:
199 return "SrcErrName";
200 case Stage1ZirInstIdEmbedFile:
201 return "SrcEmbedFile";
202 case Stage1ZirInstIdCmpxchg:
203 return "SrcCmpxchg";
204 case Stage1ZirInstIdFence:
205 return "SrcFence";
206 case Stage1ZirInstIdReduce:
207 return "SrcReduce";
208 case Stage1ZirInstIdTruncate:
209 return "SrcTruncate";
210 case Stage1ZirInstIdIntCast:
211 return "SrcIntCast";
212 case Stage1ZirInstIdFloatCast:
213 return "SrcFloatCast";
214 case Stage1ZirInstIdIntToFloat:
215 return "SrcIntToFloat";
216 case Stage1ZirInstIdFloatToInt:
217 return "SrcFloatToInt";
218 case Stage1ZirInstIdBoolToInt:
219 return "SrcBoolToInt";
220 case Stage1ZirInstIdVectorType:
221 return "SrcVectorType";
222 case Stage1ZirInstIdBoolNot:
223 return "SrcBoolNot";
224 case Stage1ZirInstIdMemset:
225 return "SrcMemset";
226 case Stage1ZirInstIdMemcpy:
227 return "SrcMemcpy";
228 case Stage1ZirInstIdSlice:
229 return "SrcSlice";
230 case Stage1ZirInstIdBreakpoint:
231 return "SrcBreakpoint";
232 case Stage1ZirInstIdReturnAddress:
233 return "SrcReturnAddress";
234 case Stage1ZirInstIdFrameAddress:
235 return "SrcFrameAddress";
236 case Stage1ZirInstIdFrameHandle:
237 return "SrcFrameHandle";
238 case Stage1ZirInstIdFrameType:
239 return "SrcFrameType";
240 case Stage1ZirInstIdFrameSize:
241 return "SrcFrameSize";
242 case Stage1ZirInstIdAlignOf:
243 return "SrcAlignOf";
244 case Stage1ZirInstIdOverflowOp:
245 return "SrcOverflowOp";
246 case Stage1ZirInstIdTestErr:
247 return "SrcTestErr";
248 case Stage1ZirInstIdMulAdd:
249 return "SrcMulAdd";
250 case Stage1ZirInstIdFloatOp:
251 return "SrcFloatOp";
252 case Stage1ZirInstIdUnwrapErrCode:
253 return "SrcUnwrapErrCode";
254 case Stage1ZirInstIdUnwrapErrPayload:
255 return "SrcUnwrapErrPayload";
256 case Stage1ZirInstIdFnProto:
257 return "SrcFnProto";
258 case Stage1ZirInstIdTestComptime:
259 return "SrcTestComptime";
260 case Stage1ZirInstIdPtrCast:
261 return "SrcPtrCast";
262 case Stage1ZirInstIdBitCast:
263 return "SrcBitCast";
264 case Stage1ZirInstIdIntToPtr:
265 return "SrcIntToPtr";
266 case Stage1ZirInstIdPtrToInt:
267 return "SrcPtrToInt";
268 case Stage1ZirInstIdIntToEnum:
269 return "SrcIntToEnum";
270 case Stage1ZirInstIdEnumToInt:
271 return "SrcEnumToInt";
272 case Stage1ZirInstIdIntToErr:
273 return "SrcIntToErr";
274 case Stage1ZirInstIdErrToInt:
275 return "SrcErrToInt";
276 case Stage1ZirInstIdCheckSwitchProngsUnderNo:
277 return "SrcCheckSwitchProngsUnderNo";
278 case Stage1ZirInstIdCheckSwitchProngsUnderYes:
279 return "SrcCheckSwitchProngsUnderYes";
280 case Stage1ZirInstIdCheckStatementIsVoid:
281 return "SrcCheckStatementIsVoid";
282 case Stage1ZirInstIdTypeName:
283 return "SrcTypeName";
284 case Stage1ZirInstIdDeclRef:
285 return "SrcDeclRef";
286 case Stage1ZirInstIdPanic:
287 return "SrcPanic";
288 case Stage1ZirInstIdTagName:
289 return "SrcTagName";
290 case Stage1ZirInstIdFieldParentPtr:
291 return "SrcFieldParentPtr";
292 case Stage1ZirInstIdOffsetOf:
293 return "SrcOffsetOf";
294 case Stage1ZirInstIdBitOffsetOf:
295 return "SrcBitOffsetOf";
296 case Stage1ZirInstIdTypeInfo:
297 return "SrcTypeInfo";
298 case Stage1ZirInstIdType:
299 return "SrcType";
300 case Stage1ZirInstIdHasField:
301 return "SrcHasField";
302 case Stage1ZirInstIdSetEvalBranchQuota:
303 return "SrcSetEvalBranchQuota";
304 case Stage1ZirInstIdPtrType:
305 return "SrcPtrType";
306 case Stage1ZirInstIdPtrTypeSimple:
307 return "SrcPtrTypeSimple";
308 case Stage1ZirInstIdPtrTypeSimpleConst:
309 return "SrcPtrTypeSimpleConst";
310 case Stage1ZirInstIdAlignCast:
311 return "SrcAlignCast";
312 case Stage1ZirInstIdImplicitCast:
313 return "SrcImplicitCast";
314 case Stage1ZirInstIdResolveResult:
315 return "SrcResolveResult";
316 case Stage1ZirInstIdResetResult:
317 return "SrcResetResult";
318 case Stage1ZirInstIdSetAlignStack:
319 return "SrcSetAlignStack";
320 case Stage1ZirInstIdArgTypeAllowVarFalse:
321 return "SrcArgTypeAllowVarFalse";
322 case Stage1ZirInstIdArgTypeAllowVarTrue:
323 return "SrcArgTypeAllowVarTrue";
324 case Stage1ZirInstIdExport:
325 return "SrcExport";
326 case Stage1ZirInstIdExtern:
327 return "SrcExtern";
328 case Stage1ZirInstIdErrorReturnTrace:
329 return "SrcErrorReturnTrace";
330 case Stage1ZirInstIdErrorUnion:
331 return "SrcErrorUnion";
332 case Stage1ZirInstIdAtomicRmw:
333 return "SrcAtomicRmw";
334 case Stage1ZirInstIdAtomicLoad:
335 return "SrcAtomicLoad";
336 case Stage1ZirInstIdAtomicStore:
337 return "SrcAtomicStore";
338 case Stage1ZirInstIdSaveErrRetAddr:
339 return "SrcSaveErrRetAddr";
340 case Stage1ZirInstIdAddImplicitReturnType:
341 return "SrcAddImplicitReturnType";
342 case Stage1ZirInstIdErrSetCast:
343 return "SrcErrSetCast";
344 case Stage1ZirInstIdCheckRuntimeScope:
345 return "SrcCheckRuntimeScope";
346 case Stage1ZirInstIdHasDecl:
347 return "SrcHasDecl";
348 case Stage1ZirInstIdUndeclaredIdent:
349 return "SrcUndeclaredIdent";
350 case Stage1ZirInstIdAlloca:
351 return "SrcAlloca";
352 case Stage1ZirInstIdEndExpr:
353 return "SrcEndExpr";
354 case Stage1ZirInstIdUnionInitNamedField:
355 return "SrcUnionInitNamedField";
356 case Stage1ZirInstIdSuspendBegin:
357 return "SrcSuspendBegin";
358 case Stage1ZirInstIdSuspendFinish:
359 return "SrcSuspendFinish";
360 case Stage1ZirInstIdAwait:
361 return "SrcAwaitSr";
362 case Stage1ZirInstIdResume:
363 return "SrcResume";
364 case Stage1ZirInstIdSpillBegin:
365 return "SrcSpillBegin";
366 case Stage1ZirInstIdSpillEnd:
367 return "SrcSpillEnd";
368 case Stage1ZirInstIdWasmMemorySize:
369 return "SrcWasmMemorySize";
370 case Stage1ZirInstIdWasmMemoryGrow:
371 return "SrcWasmMemoryGrow";
372 case Stage1ZirInstIdSrc:
373 return "SrcSrc";
374 case Stage1ZirInstIdPrefetch:
375 return "SrcPrefetch";
376 case Stage1ZirInstIdAddrSpaceCast:
377 return "SrcAddrSpaceCast";
378 }
379 zig_unreachable();
380}
381
382const char* ir_inst_gen_type_str(Stage1AirInstId id) {
383 switch (id) {
384 case Stage1AirInstIdInvalid:
385 return "GenInvalid";
386 case Stage1AirInstIdShuffleVector:
387 return "GenShuffle";
388 case Stage1AirInstIdSelect:
389 return "GenSelect";
390 case Stage1AirInstIdSplat:
391 return "GenSplat";
392 case Stage1AirInstIdDeclVar:
393 return "GenDeclVar";
394 case Stage1AirInstIdBr:
395 return "GenBr";
396 case Stage1AirInstIdCondBr:
397 return "GenCondBr";
398 case Stage1AirInstIdSwitchBr:
399 return "GenSwitchBr";
400 case Stage1AirInstIdPhi:
401 return "GenPhi";
402 case Stage1AirInstIdBinOp:
403 return "GenBinOp";
404 case Stage1AirInstIdLoadPtr:
405 return "GenLoadPtr";
406 case Stage1AirInstIdStorePtr:
407 return "GenStorePtr";
408 case Stage1AirInstIdVectorStoreElem:
409 return "GenVectorStoreElem";
410 case Stage1AirInstIdStructFieldPtr:
411 return "GenStructFieldPtr";
412 case Stage1AirInstIdUnionFieldPtr:
413 return "GenUnionFieldPtr";
414 case Stage1AirInstIdElemPtr:
415 return "GenElemPtr";
416 case Stage1AirInstIdVarPtr:
417 return "GenVarPtr";
418 case Stage1AirInstIdReturnPtr:
419 return "GenReturnPtr";
420 case Stage1AirInstIdCall:
421 return "GenCall";
422 case Stage1AirInstIdConst:
423 return "GenConst";
424 case Stage1AirInstIdReturn:
425 return "GenReturn";
426 case Stage1AirInstIdCast:
427 return "GenCast";
428 case Stage1AirInstIdUnreachable:
429 return "GenUnreachable";
430 case Stage1AirInstIdAsm:
431 return "GenAsm";
432 case Stage1AirInstIdTestNonNull:
433 return "GenTestNonNull";
434 case Stage1AirInstIdOptionalUnwrapPtr:
435 return "GenOptionalUnwrapPtr";
436 case Stage1AirInstIdOptionalWrap:
437 return "GenOptionalWrap";
438 case Stage1AirInstIdUnionTag:
439 return "GenUnionTag";
440 case Stage1AirInstIdClz:
441 return "GenClz";
442 case Stage1AirInstIdCtz:
443 return "GenCtz";
444 case Stage1AirInstIdPopCount:
445 return "GenPopCount";
446 case Stage1AirInstIdBswap:
447 return "GenBswap";
448 case Stage1AirInstIdBitReverse:
449 return "GenBitReverse";
450 case Stage1AirInstIdRef:
451 return "GenRef";
452 case Stage1AirInstIdErrName:
453 return "GenErrName";
454 case Stage1AirInstIdCmpxchg:
455 return "GenCmpxchg";
456 case Stage1AirInstIdFence:
457 return "GenFence";
458 case Stage1AirInstIdReduce:
459 return "GenReduce";
460 case Stage1AirInstIdTruncate:
461 return "GenTruncate";
462 case Stage1AirInstIdBoolNot:
463 return "GenBoolNot";
464 case Stage1AirInstIdMemset:
465 return "GenMemset";
466 case Stage1AirInstIdMemcpy:
467 return "GenMemcpy";
468 case Stage1AirInstIdSlice:
469 return "GenSlice";
470 case Stage1AirInstIdBreakpoint:
471 return "GenBreakpoint";
472 case Stage1AirInstIdReturnAddress:
473 return "GenReturnAddress";
474 case Stage1AirInstIdFrameAddress:
475 return "GenFrameAddress";
476 case Stage1AirInstIdFrameHandle:
477 return "GenFrameHandle";
478 case Stage1AirInstIdFrameSize:
479 return "GenFrameSize";
480 case Stage1AirInstIdOverflowOp:
481 return "GenOverflowOp";
482 case Stage1AirInstIdTestErr:
483 return "GenTestErr";
484 case Stage1AirInstIdMulAdd:
485 return "GenMulAdd";
486 case Stage1AirInstIdFloatOp:
487 return "GenFloatOp";
488 case Stage1AirInstIdUnwrapErrCode:
489 return "GenUnwrapErrCode";
490 case Stage1AirInstIdUnwrapErrPayload:
491 return "GenUnwrapErrPayload";
492 case Stage1AirInstIdErrWrapCode:
493 return "GenErrWrapCode";
494 case Stage1AirInstIdErrWrapPayload:
495 return "GenErrWrapPayload";
496 case Stage1AirInstIdPtrCast:
497 return "GenPtrCast";
498 case Stage1AirInstIdBitCast:
499 return "GenBitCast";
500 case Stage1AirInstIdWidenOrShorten:
501 return "GenWidenOrShorten";
502 case Stage1AirInstIdIntToPtr:
503 return "GenIntToPtr";
504 case Stage1AirInstIdPtrToInt:
505 return "GenPtrToInt";
506 case Stage1AirInstIdIntToEnum:
507 return "GenIntToEnum";
508 case Stage1AirInstIdIntToErr:
509 return "GenIntToErr";
510 case Stage1AirInstIdErrToInt:
511 return "GenErrToInt";
512 case Stage1AirInstIdPanic:
513 return "GenPanic";
514 case Stage1AirInstIdTagName:
515 return "GenTagName";
516 case Stage1AirInstIdFieldParentPtr:
517 return "GenFieldParentPtr";
518 case Stage1AirInstIdAlignCast:
519 return "GenAlignCast";
520 case Stage1AirInstIdErrorReturnTrace:
521 return "GenErrorReturnTrace";
522 case Stage1AirInstIdAtomicRmw:
523 return "GenAtomicRmw";
524 case Stage1AirInstIdAtomicLoad:
525 return "GenAtomicLoad";
526 case Stage1AirInstIdAtomicStore:
527 return "GenAtomicStore";
528 case Stage1AirInstIdSaveErrRetAddr:
529 return "GenSaveErrRetAddr";
530 case Stage1AirInstIdVectorToArray:
531 return "GenVectorToArray";
532 case Stage1AirInstIdArrayToVector:
533 return "GenArrayToVector";
534 case Stage1AirInstIdAssertZero:
535 return "GenAssertZero";
536 case Stage1AirInstIdAssertNonNull:
537 return "GenAssertNonNull";
538 case Stage1AirInstIdAlloca:
539 return "GenAlloca";
540 case Stage1AirInstIdPtrOfArrayToSlice:
541 return "GenPtrOfArrayToSlice";
542 case Stage1AirInstIdSuspendBegin:
543 return "GenSuspendBegin";
544 case Stage1AirInstIdSuspendFinish:
545 return "GenSuspendFinish";
546 case Stage1AirInstIdAwait:
547 return "GenAwait";
548 case Stage1AirInstIdResume:
549 return "GenResume";
550 case Stage1AirInstIdSpillBegin:
551 return "GenSpillBegin";
552 case Stage1AirInstIdSpillEnd:
553 return "GenSpillEnd";
554 case Stage1AirInstIdVectorExtractElem:
555 return "GenVectorExtractElem";
556 case Stage1AirInstIdBinaryNot:
557 return "GenBinaryNot";
558 case Stage1AirInstIdNegation:
559 return "GenNegation";
560 case Stage1AirInstIdWasmMemorySize:
561 return "GenWasmMemorySize";
562 case Stage1AirInstIdWasmMemoryGrow:
563 return "GenWasmMemoryGrow";
564 case Stage1AirInstIdExtern:
565 return "GenExtern";
566 case Stage1AirInstIdPrefetch:
567 return "GenPrefetch";
568 }
569 zig_unreachable();
570}
571
572static void ir_print_indent_src(IrPrintSrc *irp) {
573 for (int i = 0; i < irp->indent; i += 1) {
574 fprintf(irp->f, " ");
575 }
576}
577
578static void ir_print_indent_gen(IrPrintGen *irp) {
579 for (int i = 0; i < irp->indent; i += 1) {
580 fprintf(irp->f, " ");
581 }
582}
583
584static void ir_print_prefix_src(IrPrintSrc *irp, Stage1ZirInst *instruction, bool trailing) {
585 ir_print_indent_src(irp);
586 const char mark = trailing ? ':' : '#';
587 const char *type_name;
588 if (instruction->id == Stage1ZirInstIdConst) {
589 type_name = buf_ptr(&reinterpret_cast<Stage1ZirInstConst *>(instruction)->value->type->name);
590 } else {
591 type_name = "(unknown)";
592 }
593 const char *ref_count = ir_inst_src_has_side_effects(instruction) ?
594 "-" : buf_ptr(buf_sprintf("%" PRIu32 "", instruction->ref_count));
595 fprintf(irp->f, "%c%-3" PRIu32 "| %-22s| %-12s| %-2s| ", mark, instruction->debug_id,
596 ir_inst_src_type_str(instruction->id), type_name, ref_count);
597}
598
599static void ir_print_prefix_gen(IrPrintGen *irp, Stage1AirInst *instruction, bool trailing) {
600 ir_print_indent_gen(irp);
601 const char mark = trailing ? ':' : '#';
602 const char *type_name = instruction->value->type ? buf_ptr(&instruction->value->type->name) : "(unknown)";
603 const char *ref_count = ir_inst_gen_has_side_effects(instruction) ?
604 "-" : buf_ptr(buf_sprintf("%" PRIu32 "", instruction->ref_count));
605 fprintf(irp->f, "%c%-3" PRIu32 "| %-22s| %-12s| %-2s| ", mark, instruction->debug_id,
606 ir_inst_gen_type_str(instruction->id), type_name, ref_count);
607}
608
609static void ir_print_var_src(IrPrintSrc *irp, Stage1ZirInst *inst) {
610 fprintf(irp->f, "#%" PRIu32 "", inst->debug_id);
611}
612
613static void ir_print_var_gen(IrPrintGen *irp, Stage1AirInst *inst) {
614 fprintf(irp->f, "#%" PRIu32 "", inst->debug_id);
615 if (irp->printed.maybe_get(inst) == nullptr) {
616 irp->printed.put(inst, 0);
617 irp->pending.append(inst);
618 }
619}
620
621static void ir_print_other_inst_src(IrPrintSrc *irp, Stage1ZirInst *inst) {
622 if (inst == nullptr) {
623 fprintf(irp->f, "(null)");
624 return;
625 }
626 ir_print_var_src(irp, inst);
627}
628
629static void ir_print_const_value(CodeGen *g, FILE *f, ZigValue *const_val) {
630 Buf buf = BUF_INIT;
631 buf_resize(&buf, 0);
632 render_const_value(g, &buf, const_val);
633 fprintf(f, "%s", buf_ptr(&buf));
634}
635
636static void ir_print_other_inst_gen(IrPrintGen *irp, Stage1AirInst *inst) {
637 if (inst == nullptr) {
638 fprintf(irp->f, "(null)");
639 } else {
640 ir_print_var_gen(irp, inst);
641 }
642}
643
644static void ir_print_other_block(IrPrintSrc *irp, Stage1ZirBasicBlock *bb) {
645 if (bb == nullptr) {
646 fprintf(irp->f, "(null block)");
647 } else {
648 fprintf(irp->f, "$%s_%" PRIu32 "", bb->name_hint, bb->debug_id);
649 }
650}
651
652static void ir_print_other_block_gen(IrPrintGen *irp, Stage1AirBasicBlock *bb) {
653 if (bb == nullptr) {
654 fprintf(irp->f, "(null block)");
655 } else {
656 fprintf(irp->f, "$%s_%" PRIu32 "", bb->name_hint, bb->debug_id);
657 }
658}
659
660static void ir_print_return_src(IrPrintSrc *irp, Stage1ZirInstReturn *inst) {
661 fprintf(irp->f, "return ");
662 ir_print_other_inst_src(irp, inst->operand);
663}
664
665static void ir_print_return_gen(IrPrintGen *irp, Stage1AirInstReturn *inst) {
666 fprintf(irp->f, "return ");
667 ir_print_other_inst_gen(irp, inst->operand);
668}
669
670static void ir_print_const(IrPrintSrc *irp, Stage1ZirInstConst *const_instruction) {
671 ir_print_const_value(irp->codegen, irp->f, const_instruction->value);
672}
673
674static void ir_print_const(IrPrintGen *irp, Stage1AirInstConst *const_instruction) {
675 ir_print_const_value(irp->codegen, irp->f, const_instruction->base.value);
676}
677
678static const char *ir_bin_op_id_str(IrBinOp op_id) {
679 switch (op_id) {
680 case IrBinOpInvalid:
681 zig_unreachable();
682 case IrBinOpBoolOr:
683 return "BoolOr";
684 case IrBinOpBoolAnd:
685 return "BoolAnd";
686 case IrBinOpCmpEq:
687 return "==";
688 case IrBinOpCmpNotEq:
689 return "!=";
690 case IrBinOpCmpLessThan:
691 return "<";
692 case IrBinOpCmpGreaterThan:
693 return ">";
694 case IrBinOpCmpLessOrEq:
695 return "<=";
696 case IrBinOpCmpGreaterOrEq:
697 return ">=";
698 case IrBinOpBinOr:
699 return "|";
700 case IrBinOpBinXor:
701 return "^";
702 case IrBinOpBinAnd:
703 return "&";
704 case IrBinOpBitShiftLeftLossy:
705 return "<<";
706 case IrBinOpBitShiftLeftExact:
707 return "@shlExact";
708 case IrBinOpBitShiftRightLossy:
709 return ">>";
710 case IrBinOpBitShiftRightExact:
711 return "@shrExact";
712 case IrBinOpAdd:
713 return "+";
714 case IrBinOpAddWrap:
715 return "+%";
716 case IrBinOpSub:
717 return "-";
718 case IrBinOpSubWrap:
719 return "-%";
720 case IrBinOpMult:
721 return "*";
722 case IrBinOpMultWrap:
723 return "*%";
724 case IrBinOpDivUnspecified:
725 return "/";
726 case IrBinOpDivTrunc:
727 return "@divTrunc";
728 case IrBinOpDivFloor:
729 return "@divFloor";
730 case IrBinOpDivExact:
731 return "@divExact";
732 case IrBinOpRemUnspecified:
733 return "%";
734 case IrBinOpRemRem:
735 return "@rem";
736 case IrBinOpRemMod:
737 return "@mod";
738 case IrBinOpArrayCat:
739 return "++";
740 case IrBinOpArrayMult:
741 return "**";
742 case IrBinOpMax:
743 return "@max";
744 case IrBinOpMin:
745 return "@min";
746 case IrBinOpAddSat:
747 return "@addWithSaturation";
748 case IrBinOpSubSat:
749 return "@subWithSaturation";
750 case IrBinOpMultSat:
751 return "@mulWithSaturation";
752 case IrBinOpShlSat:
753 return "@shlWithSaturation";
754 }
755 zig_unreachable();
756}
757
758static const char *ir_un_op_id_str(IrUnOp op_id) {
759 switch (op_id) {
760 case IrUnOpInvalid:
761 zig_unreachable();
762 case IrUnOpBinNot:
763 return "~";
764 case IrUnOpNegation:
765 return "-";
766 case IrUnOpNegationWrap:
767 return "-%";
768 case IrUnOpDereference:
769 return "*";
770 case IrUnOpOptional:
771 return "?";
772 }
773 zig_unreachable();
774}
775
776static void ir_print_un_op(IrPrintSrc *irp, Stage1ZirInstUnOp *inst) {
777 fprintf(irp->f, "%s ", ir_un_op_id_str(inst->op_id));
778 ir_print_other_inst_src(irp, inst->value);
779}
780
781static void ir_print_bin_op(IrPrintSrc *irp, Stage1ZirInstBinOp *bin_op_instruction) {
782 ir_print_other_inst_src(irp, bin_op_instruction->op1);
783 fprintf(irp->f, " %s ", ir_bin_op_id_str(bin_op_instruction->op_id));
784 ir_print_other_inst_src(irp, bin_op_instruction->op2);
785 if (!bin_op_instruction->safety_check_on) {
786 fprintf(irp->f, " // no safety");
787 }
788}
789
790static void ir_print_bin_op(IrPrintGen *irp, Stage1AirInstBinOp *bin_op_instruction) {
791 ir_print_other_inst_gen(irp, bin_op_instruction->op1);
792 fprintf(irp->f, " %s ", ir_bin_op_id_str(bin_op_instruction->op_id));
793 ir_print_other_inst_gen(irp, bin_op_instruction->op2);
794 if (!bin_op_instruction->safety_check_on) {
795 fprintf(irp->f, " // no safety");
796 }
797}
798
799static void ir_print_merge_err_sets(IrPrintSrc *irp, Stage1ZirInstMergeErrSets *instruction) {
800 ir_print_other_inst_src(irp, instruction->op1);
801 fprintf(irp->f, " || ");
802 ir_print_other_inst_src(irp, instruction->op2);
803 if (instruction->type_name != nullptr) {
804 fprintf(irp->f, " // name=%s", buf_ptr(instruction->type_name));
805 }
806}
807
808static void ir_print_decl_var_src(IrPrintSrc *irp, Stage1ZirInstDeclVar *decl_var_instruction) {
809 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
810 const char *name = decl_var_instruction->var->name;
811 if (decl_var_instruction->var_type) {
812 fprintf(irp->f, "%s %s: ", var_or_const, name);
813 ir_print_other_inst_src(irp, decl_var_instruction->var_type);
814 fprintf(irp->f, " ");
815 } else {
816 fprintf(irp->f, "%s %s ", var_or_const, name);
817 }
818 if (decl_var_instruction->align_value) {
819 fprintf(irp->f, "align ");
820 ir_print_other_inst_src(irp, decl_var_instruction->align_value);
821 fprintf(irp->f, " ");
822 }
823 fprintf(irp->f, "= ");
824 ir_print_other_inst_src(irp, decl_var_instruction->ptr);
825 if (decl_var_instruction->var->is_comptime != nullptr) {
826 fprintf(irp->f, " // comptime = ");
827 ir_print_other_inst_src(irp, decl_var_instruction->var->is_comptime);
828 }
829}
830
831static const char *cast_op_str(CastOp op) {
832 switch (op) {
833 case CastOpNoCast: return "NoCast";
834 case CastOpNoop: return "NoOp";
835 case CastOpIntToFloat: return "IntToFloat";
836 case CastOpFloatToInt: return "FloatToInt";
837 case CastOpBoolToInt: return "BoolToInt";
838 case CastOpNumLitToConcrete: return "NumLitToConcrete";
839 case CastOpErrSet: return "ErrSet";
840 case CastOpBitCast: return "BitCast";
841 }
842 zig_unreachable();
843}
844
845static void ir_print_cast(IrPrintGen *irp, Stage1AirInstCast *cast_instruction) {
846 fprintf(irp->f, "%s cast ", cast_op_str(cast_instruction->cast_op));
847 ir_print_other_inst_gen(irp, cast_instruction->value);
848}
849
850static void ir_print_result_loc_var(IrPrintSrc *irp, ResultLocVar *result_loc_var) {
851 fprintf(irp->f, "var(");
852 ir_print_other_inst_src(irp, result_loc_var->base.source_instruction);
853 fprintf(irp->f, ")");
854}
855
856static void ir_print_result_loc_instruction(IrPrintSrc *irp, ResultLocInstruction *result_loc_inst) {
857 fprintf(irp->f, "inst(");
858 ir_print_other_inst_src(irp, result_loc_inst->base.source_instruction);
859 fprintf(irp->f, ")");
860}
861
862static void ir_print_result_loc_peer(IrPrintSrc *irp, ResultLocPeer *result_loc_peer) {
863 fprintf(irp->f, "peer(next=");
864 ir_print_other_block(irp, result_loc_peer->next_bb);
865 fprintf(irp->f, ")");
866}
867
868static void ir_print_result_loc_bit_cast(IrPrintSrc *irp, ResultLocBitCast *result_loc_bit_cast) {
869 fprintf(irp->f, "bitcast(ty=");
870 ir_print_other_inst_src(irp, result_loc_bit_cast->base.source_instruction);
871 fprintf(irp->f, ")");
872}
873
874static void ir_print_result_loc_cast(IrPrintSrc *irp, ResultLocCast *result_loc_cast) {
875 fprintf(irp->f, "cast(ty=");
876 ir_print_other_inst_src(irp, result_loc_cast->base.source_instruction);
877 fprintf(irp->f, ")");
878}
879
880static void ir_print_result_loc(IrPrintSrc *irp, ResultLoc *result_loc) {
881 switch (result_loc->id) {
882 case ResultLocIdInvalid:
883 zig_unreachable();
884 case ResultLocIdNone:
885 fprintf(irp->f, "none");
886 return;
887 case ResultLocIdReturn:
888 fprintf(irp->f, "return");
889 return;
890 case ResultLocIdVar:
891 return ir_print_result_loc_var(irp, (ResultLocVar *)result_loc);
892 case ResultLocIdInstruction:
893 return ir_print_result_loc_instruction(irp, (ResultLocInstruction *)result_loc);
894 case ResultLocIdPeer:
895 return ir_print_result_loc_peer(irp, (ResultLocPeer *)result_loc);
896 case ResultLocIdBitCast:
897 return ir_print_result_loc_bit_cast(irp, (ResultLocBitCast *)result_loc);
898 case ResultLocIdCast:
899 return ir_print_result_loc_cast(irp, (ResultLocCast *)result_loc);
900 case ResultLocIdPeerParent:
901 fprintf(irp->f, "peer_parent");
902 return;
903 }
904 zig_unreachable();
905}
906
907static void ir_print_call_extra(IrPrintSrc *irp, Stage1ZirInstCallExtra *instruction) {
908 fprintf(irp->f, "opts=");
909 ir_print_other_inst_src(irp, instruction->options);
910 fprintf(irp->f, ", fn=");
911 ir_print_other_inst_src(irp, instruction->fn_ref);
912 fprintf(irp->f, ", args=");
913 ir_print_other_inst_src(irp, instruction->args);
914 fprintf(irp->f, ", result=");
915 ir_print_result_loc(irp, instruction->result_loc);
916}
917
918static void ir_print_async_call_extra(IrPrintSrc *irp, Stage1ZirInstAsyncCallExtra *instruction) {
919 fprintf(irp->f, "modifier=");
920 ir_print_call_modifier(irp->f, instruction->modifier);
921 fprintf(irp->f, ", fn=");
922 ir_print_other_inst_src(irp, instruction->fn_ref);
923 if (instruction->ret_ptr != nullptr) {
924 fprintf(irp->f, ", ret_ptr=");
925 ir_print_other_inst_src(irp, instruction->ret_ptr);
926 }
927 fprintf(irp->f, ", new_stack=");
928 ir_print_other_inst_src(irp, instruction->new_stack);
929 fprintf(irp->f, ", args=");
930 ir_print_other_inst_src(irp, instruction->args);
931 fprintf(irp->f, ", result=");
932 ir_print_result_loc(irp, instruction->result_loc);
933}
934
935static void ir_print_call_args(IrPrintSrc *irp, Stage1ZirInstCallArgs *instruction) {
936 fprintf(irp->f, "opts=");
937 ir_print_other_inst_src(irp, instruction->options);
938 fprintf(irp->f, ", fn=");
939 ir_print_other_inst_src(irp, instruction->fn_ref);
940 fprintf(irp->f, ", args=(");
941 for (size_t i = 0; i < instruction->args_len; i += 1) {
942 Stage1ZirInst *arg = instruction->args_ptr[i];
943 if (i != 0)
944 fprintf(irp->f, ", ");
945 ir_print_other_inst_src(irp, arg);
946 }
947 fprintf(irp->f, "), result=");
948 ir_print_result_loc(irp, instruction->result_loc);
949}
950
951static void ir_print_call_src(IrPrintSrc *irp, Stage1ZirInstCall *call_instruction) {
952 ir_print_call_modifier(irp->f, call_instruction->modifier);
953 if (call_instruction->fn_entry) {
954 fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
955 } else {
956 assert(call_instruction->fn_ref);
957 ir_print_other_inst_src(irp, call_instruction->fn_ref);
958 }
959 fprintf(irp->f, "(");
960 for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
961 Stage1ZirInst *arg = call_instruction->args[i];
962 if (i != 0)
963 fprintf(irp->f, ", ");
964 ir_print_other_inst_src(irp, arg);
965 }
966 fprintf(irp->f, ")result=");
967 ir_print_result_loc(irp, call_instruction->result_loc);
968}
969
970static void ir_print_call_gen(IrPrintGen *irp, Stage1AirInstCall *call_instruction) {
971 ir_print_call_modifier(irp->f, call_instruction->modifier);
972 if (call_instruction->fn_entry) {
973 fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
974 } else {
975 assert(call_instruction->fn_ref);
976 ir_print_other_inst_gen(irp, call_instruction->fn_ref);
977 }
978 fprintf(irp->f, "(");
979 for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
980 Stage1AirInst *arg = call_instruction->args[i];
981 if (i != 0)
982 fprintf(irp->f, ", ");
983 ir_print_other_inst_gen(irp, arg);
984 }
985 fprintf(irp->f, ")result=");
986 ir_print_other_inst_gen(irp, call_instruction->result_loc);
987}
988
989static void ir_print_cond_br(IrPrintSrc *irp, Stage1ZirInstCondBr *inst) {
990 fprintf(irp->f, "if (");
991 ir_print_other_inst_src(irp, inst->condition);
992 fprintf(irp->f, ") ");
993 ir_print_other_block(irp, inst->then_block);
994 fprintf(irp->f, " else ");
995 ir_print_other_block(irp, inst->else_block);
996 if (inst->is_comptime != nullptr) {
997 fprintf(irp->f, " // comptime = ");
998 ir_print_other_inst_src(irp, inst->is_comptime);
999 }
1000}
1001
1002static void ir_print_cond_br(IrPrintGen *irp, Stage1AirInstCondBr *inst) {
1003 fprintf(irp->f, "if (");
1004 ir_print_other_inst_gen(irp, inst->condition);
1005 fprintf(irp->f, ") ");
1006 ir_print_other_block_gen(irp, inst->then_block);
1007 fprintf(irp->f, " else ");
1008 ir_print_other_block_gen(irp, inst->else_block);
1009}
1010
1011static void ir_print_br(IrPrintSrc *irp, Stage1ZirInstBr *br_instruction) {
1012 fprintf(irp->f, "goto ");
1013 ir_print_other_block(irp, br_instruction->dest_block);
1014 if (br_instruction->is_comptime != nullptr) {
1015 fprintf(irp->f, " // comptime = ");
1016 ir_print_other_inst_src(irp, br_instruction->is_comptime);
1017 }
1018}
1019
1020static void ir_print_br(IrPrintGen *irp, Stage1AirInstBr *inst) {
1021 fprintf(irp->f, "goto ");
1022 ir_print_other_block_gen(irp, inst->dest_block);
1023}
1024
1025static void ir_print_phi(IrPrintSrc *irp, Stage1ZirInstPhi *phi_instruction) {
1026 assert(phi_instruction->incoming_count != 0);
1027 assert(phi_instruction->incoming_count != SIZE_MAX);
1028 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
1029 Stage1ZirBasicBlock *incoming_block = phi_instruction->incoming_blocks[i];
1030 Stage1ZirInst *incoming_value = phi_instruction->incoming_values[i];
1031 if (i != 0)
1032 fprintf(irp->f, " ");
1033 ir_print_other_block(irp, incoming_block);
1034 fprintf(irp->f, ":");
1035 ir_print_other_inst_src(irp, incoming_value);
1036 }
1037}
1038
1039static void ir_print_phi(IrPrintGen *irp, Stage1AirInstPhi *phi_instruction) {
1040 assert(phi_instruction->incoming_count != 0);
1041 assert(phi_instruction->incoming_count != SIZE_MAX);
1042 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
1043 Stage1AirBasicBlock *incoming_block = phi_instruction->incoming_blocks[i];
1044 Stage1AirInst *incoming_value = phi_instruction->incoming_values[i];
1045 if (i != 0)
1046 fprintf(irp->f, " ");
1047 ir_print_other_block_gen(irp, incoming_block);
1048 fprintf(irp->f, ":");
1049 ir_print_other_inst_gen(irp, incoming_value);
1050 }
1051}
1052
1053static void ir_print_container_init_list(IrPrintSrc *irp, Stage1ZirInstContainerInitList *instruction) {
1054 fprintf(irp->f, "{");
1055 if (instruction->item_count > 50) {
1056 fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count);
1057 } else {
1058 for (size_t i = 0; i < instruction->item_count; i += 1) {
1059 Stage1ZirInst *result_loc = instruction->elem_result_loc_list[i];
1060 if (i != 0)
1061 fprintf(irp->f, ", ");
1062 ir_print_other_inst_src(irp, result_loc);
1063 }
1064 }
1065 fprintf(irp->f, "}result=");
1066 ir_print_other_inst_src(irp, instruction->result_loc);
1067}
1068
1069static void ir_print_container_init_fields(IrPrintSrc *irp, Stage1ZirInstContainerInitFields *instruction) {
1070 fprintf(irp->f, "{");
1071 for (size_t i = 0; i < instruction->field_count; i += 1) {
1072 Stage1ZirInstContainerInitFieldsField *field = &instruction->fields[i];
1073 const char *comma = (i == 0) ? "" : ", ";
1074 fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name));
1075 ir_print_other_inst_src(irp, field->result_loc);
1076 }
1077 fprintf(irp->f, "}result=");
1078 ir_print_other_inst_src(irp, instruction->result_loc);
1079}
1080
1081static void ir_print_unreachable(IrPrintSrc *irp, Stage1ZirInstUnreachable *instruction) {
1082 fprintf(irp->f, "unreachable");
1083}
1084
1085static void ir_print_unreachable(IrPrintGen *irp, Stage1AirInstUnreachable *instruction) {
1086 fprintf(irp->f, "unreachable");
1087}
1088
1089static void ir_print_elem_ptr(IrPrintSrc *irp, Stage1ZirInstElemPtr *instruction) {
1090 fprintf(irp->f, "&");
1091 ir_print_other_inst_src(irp, instruction->array_ptr);
1092 fprintf(irp->f, "[");
1093 ir_print_other_inst_src(irp, instruction->elem_index);
1094 fprintf(irp->f, "]");
1095 if (!instruction->safety_check_on) {
1096 fprintf(irp->f, " // no safety");
1097 }
1098}
1099
1100static void ir_print_elem_ptr(IrPrintGen *irp, Stage1AirInstElemPtr *instruction) {
1101 fprintf(irp->f, "&");
1102 ir_print_other_inst_gen(irp, instruction->array_ptr);
1103 fprintf(irp->f, "[");
1104 ir_print_other_inst_gen(irp, instruction->elem_index);
1105 fprintf(irp->f, "]");
1106 if (!instruction->safety_check_on) {
1107 fprintf(irp->f, " // no safety");
1108 }
1109}
1110
1111static void ir_print_var_ptr(IrPrintSrc *irp, Stage1ZirInstVarPtr *instruction) {
1112 fprintf(irp->f, "&%s", instruction->var->name);
1113}
1114
1115static void ir_print_var_ptr(IrPrintGen *irp, Stage1AirInstVarPtr *instruction) {
1116 fprintf(irp->f, "&%s", instruction->var->name);
1117}
1118
1119static void ir_print_return_ptr(IrPrintGen *irp, Stage1AirInstReturnPtr *instruction) {
1120 fprintf(irp->f, "@ReturnPtr");
1121}
1122
1123static void ir_print_load_ptr(IrPrintSrc *irp, Stage1ZirInstLoadPtr *instruction) {
1124 ir_print_other_inst_src(irp, instruction->ptr);
1125 fprintf(irp->f, ".*");
1126}
1127
1128static void ir_print_load_ptr_gen(IrPrintGen *irp, Stage1AirInstLoadPtr *instruction) {
1129 fprintf(irp->f, "loadptr(");
1130 ir_print_other_inst_gen(irp, instruction->ptr);
1131 fprintf(irp->f, ")result=");
1132 ir_print_other_inst_gen(irp, instruction->result_loc);
1133}
1134
1135static void ir_print_store_ptr(IrPrintSrc *irp, Stage1ZirInstStorePtr *instruction) {
1136 fprintf(irp->f, "*");
1137 ir_print_var_src(irp, instruction->ptr);
1138 fprintf(irp->f, " = ");
1139 ir_print_other_inst_src(irp, instruction->value);
1140}
1141
1142static void ir_print_store_ptr(IrPrintGen *irp, Stage1AirInstStorePtr *instruction) {
1143 fprintf(irp->f, "*");
1144 ir_print_var_gen(irp, instruction->ptr);
1145 fprintf(irp->f, " = ");
1146 ir_print_other_inst_gen(irp, instruction->value);
1147}
1148
1149static void ir_print_vector_store_elem(IrPrintGen *irp, Stage1AirInstVectorStoreElem *instruction) {
1150 fprintf(irp->f, "vector_ptr=");
1151 ir_print_var_gen(irp, instruction->vector_ptr);
1152 fprintf(irp->f, ",index=");
1153 ir_print_var_gen(irp, instruction->index);
1154 fprintf(irp->f, ",value=");
1155 ir_print_other_inst_gen(irp, instruction->value);
1156}
1157
1158static void ir_print_typeof(IrPrintSrc *irp, Stage1ZirInstTypeOf *instruction) {
1159 fprintf(irp->f, "@TypeOf(");
1160 if (instruction->value_count == 1) {
1161 ir_print_other_inst_src(irp, instruction->value.scalar);
1162 } else {
1163 for (size_t i = 0; i < instruction->value_count; i += 1) {
1164 ir_print_other_inst_src(irp, instruction->value.list[i]);
1165 }
1166 }
1167 fprintf(irp->f, ")");
1168}
1169
1170static void ir_print_binary_not(IrPrintGen *irp, Stage1AirInstBinaryNot *instruction) {
1171 fprintf(irp->f, "~");
1172 ir_print_other_inst_gen(irp, instruction->operand);
1173}
1174
1175static void ir_print_negation(IrPrintGen *irp, Stage1AirInstNegation *instruction) {
1176 fprintf(irp->f, instruction->wrapping ? "-%%" : "-");
1177 ir_print_other_inst_gen(irp, instruction->operand);
1178}
1179
1180static void ir_print_field_ptr(IrPrintSrc *irp, Stage1ZirInstFieldPtr *instruction) {
1181 if (instruction->field_name_buffer) {
1182 fprintf(irp->f, "fieldptr ");
1183 ir_print_other_inst_src(irp, instruction->container_ptr);
1184 fprintf(irp->f, ".%s", buf_ptr(instruction->field_name_buffer));
1185 } else {
1186 assert(instruction->field_name_expr);
1187 fprintf(irp->f, "@field(");
1188 ir_print_other_inst_src(irp, instruction->container_ptr);
1189 fprintf(irp->f, ", ");
1190 ir_print_other_inst_src(irp, instruction->field_name_expr);
1191 fprintf(irp->f, ")");
1192 }
1193}
1194
1195static void ir_print_struct_field_ptr(IrPrintGen *irp, Stage1AirInstStructFieldPtr *instruction) {
1196 fprintf(irp->f, "@StructFieldPtr(&");
1197 ir_print_other_inst_gen(irp, instruction->struct_ptr);
1198 fprintf(irp->f, ".%s", buf_ptr(instruction->field->name));
1199 fprintf(irp->f, ")");
1200}
1201
1202static void ir_print_union_field_ptr(IrPrintGen *irp, Stage1AirInstUnionFieldPtr *instruction) {
1203 fprintf(irp->f, "@UnionFieldPtr(&");
1204 ir_print_other_inst_gen(irp, instruction->union_ptr);
1205 fprintf(irp->f, ".%s", buf_ptr(instruction->field->enum_field->name));
1206 fprintf(irp->f, ")");
1207}
1208
1209static void ir_print_set_cold(IrPrintSrc *irp, Stage1ZirInstSetCold *instruction) {
1210 fprintf(irp->f, "@setCold(");
1211 ir_print_other_inst_src(irp, instruction->is_cold);
1212 fprintf(irp->f, ")");
1213}
1214
1215static void ir_print_set_runtime_safety(IrPrintSrc *irp, Stage1ZirInstSetRuntimeSafety *instruction) {
1216 fprintf(irp->f, "@setRuntimeSafety(");
1217 ir_print_other_inst_src(irp, instruction->safety_on);
1218 fprintf(irp->f, ")");
1219}
1220
1221static void ir_print_set_float_mode(IrPrintSrc *irp, Stage1ZirInstSetFloatMode *instruction) {
1222 fprintf(irp->f, "@setFloatMode(");
1223 ir_print_other_inst_src(irp, instruction->scope_value);
1224 fprintf(irp->f, ", ");
1225 ir_print_other_inst_src(irp, instruction->mode_value);
1226 fprintf(irp->f, ")");
1227}
1228
1229static void ir_print_array_type(IrPrintSrc *irp, Stage1ZirInstArrayType *instruction) {
1230 fprintf(irp->f, "[");
1231 ir_print_other_inst_src(irp, instruction->size);
1232 if (instruction->sentinel != nullptr) {
1233 fprintf(irp->f, ":");
1234 ir_print_other_inst_src(irp, instruction->sentinel);
1235 }
1236 fprintf(irp->f, "]");
1237 ir_print_other_inst_src(irp, instruction->child_type);
1238}
1239
1240static void ir_print_slice_type(IrPrintSrc *irp, Stage1ZirInstSliceType *instruction) {
1241 const char *const_kw = instruction->is_const ? "const " : "";
1242 fprintf(irp->f, "[]%s", const_kw);
1243 ir_print_other_inst_src(irp, instruction->child_type);
1244}
1245
1246static void ir_print_any_frame_type(IrPrintSrc *irp, Stage1ZirInstAnyFrameType *instruction) {
1247 if (instruction->payload_type == nullptr) {
1248 fprintf(irp->f, "anyframe");
1249 } else {
1250 fprintf(irp->f, "anyframe->");
1251 ir_print_other_inst_src(irp, instruction->payload_type);
1252 }
1253}
1254
1255static void ir_print_asm_src(IrPrintSrc *irp, Stage1ZirInstAsm *instruction) {
1256 assert(instruction->base.source_node->type == NodeTypeAsmExpr);
1257 AstNodeAsmExpr *asm_expr = &instruction->base.source_node->data.asm_expr;
1258 const char *volatile_kw = instruction->has_side_effects ? " volatile" : "";
1259 fprintf(irp->f, "asm%s (", volatile_kw);
1260 ir_print_other_inst_src(irp, instruction->asm_template);
1261
1262 for (size_t i = 0; i < asm_expr->output_list.length; i += 1) {
1263 AsmOutput *asm_output = asm_expr->output_list.at(i);
1264 if (i != 0) fprintf(irp->f, ", ");
1265
1266 fprintf(irp->f, "[%s] \"%s\" (",
1267 buf_ptr(asm_output->asm_symbolic_name),
1268 buf_ptr(asm_output->constraint));
1269 if (asm_output->return_type) {
1270 fprintf(irp->f, "-> ");
1271 ir_print_other_inst_src(irp, instruction->output_types[i]);
1272 } else {
1273 fprintf(irp->f, "%s", buf_ptr(asm_output->variable_name));
1274 }
1275 fprintf(irp->f, ")");
1276 }
1277
1278 fprintf(irp->f, " : ");
1279 for (size_t i = 0; i < asm_expr->input_list.length; i += 1) {
1280 AsmInput *asm_input = asm_expr->input_list.at(i);
1281
1282 if (i != 0) fprintf(irp->f, ", ");
1283 fprintf(irp->f, "[%s] \"%s\" (",
1284 buf_ptr(asm_input->asm_symbolic_name),
1285 buf_ptr(asm_input->constraint));
1286 ir_print_other_inst_src(irp, instruction->input_list[i]);
1287 fprintf(irp->f, ")");
1288 }
1289 fprintf(irp->f, " : ");
1290 for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1) {
1291 Buf *reg_name = asm_expr->clobber_list.at(i);
1292 if (i != 0) fprintf(irp->f, ", ");
1293 fprintf(irp->f, "\"%s\"", buf_ptr(reg_name));
1294 }
1295 fprintf(irp->f, ")");
1296}
1297
1298static void ir_print_asm_gen(IrPrintGen *irp, Stage1AirInstAsm *instruction) {
1299 assert(instruction->base.source_node->type == NodeTypeAsmExpr);
1300 AstNodeAsmExpr *asm_expr = &instruction->base.source_node->data.asm_expr;
1301 const char *volatile_kw = instruction->has_side_effects ? " volatile" : "";
1302 fprintf(irp->f, "asm%s (\"%s\") : ", volatile_kw, buf_ptr(instruction->asm_template));
1303
1304 for (size_t i = 0; i < asm_expr->output_list.length; i += 1) {
1305 AsmOutput *asm_output = asm_expr->output_list.at(i);
1306 if (i != 0) fprintf(irp->f, ", ");
1307
1308 fprintf(irp->f, "[%s] \"%s\" (",
1309 buf_ptr(asm_output->asm_symbolic_name),
1310 buf_ptr(asm_output->constraint));
1311 if (asm_output->return_type) {
1312 fprintf(irp->f, "-> ");
1313 ir_print_other_inst_gen(irp, instruction->output_types[i]);
1314 } else {
1315 fprintf(irp->f, "%s", buf_ptr(asm_output->variable_name));
1316 }
1317 fprintf(irp->f, ")");
1318 }
1319
1320 fprintf(irp->f, " : ");
1321 for (size_t i = 0; i < asm_expr->input_list.length; i += 1) {
1322 AsmInput *asm_input = asm_expr->input_list.at(i);
1323
1324 if (i != 0) fprintf(irp->f, ", ");
1325 fprintf(irp->f, "[%s] \"%s\" (",
1326 buf_ptr(asm_input->asm_symbolic_name),
1327 buf_ptr(asm_input->constraint));
1328 ir_print_other_inst_gen(irp, instruction->input_list[i]);
1329 fprintf(irp->f, ")");
1330 }
1331 fprintf(irp->f, " : ");
1332 for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1) {
1333 Buf *reg_name = asm_expr->clobber_list.at(i);
1334 if (i != 0) fprintf(irp->f, ", ");
1335 fprintf(irp->f, "\"%s\"", buf_ptr(reg_name));
1336 }
1337 fprintf(irp->f, ")");
1338}
1339
1340static void ir_print_size_of(IrPrintSrc *irp, Stage1ZirInstSizeOf *instruction) {
1341 if (instruction->bit_size)
1342 fprintf(irp->f, "@bitSizeOf(");
1343 else
1344 fprintf(irp->f, "@sizeOf(");
1345 ir_print_other_inst_src(irp, instruction->type_value);
1346 fprintf(irp->f, ")");
1347}
1348
1349static void ir_print_test_non_null(IrPrintSrc *irp, Stage1ZirInstTestNonNull *instruction) {
1350 ir_print_other_inst_src(irp, instruction->value);
1351 fprintf(irp->f, " != null");
1352}
1353
1354static void ir_print_test_non_null(IrPrintGen *irp, Stage1AirInstTestNonNull *instruction) {
1355 ir_print_other_inst_gen(irp, instruction->value);
1356 fprintf(irp->f, " != null");
1357}
1358
1359static void ir_print_optional_unwrap_ptr(IrPrintSrc *irp, Stage1ZirInstOptionalUnwrapPtr *instruction) {
1360 fprintf(irp->f, "&");
1361 ir_print_other_inst_src(irp, instruction->base_ptr);
1362 fprintf(irp->f, ".*.?");
1363 if (!instruction->safety_check_on) {
1364 fprintf(irp->f, " // no safety");
1365 }
1366}
1367
1368static void ir_print_optional_unwrap_ptr(IrPrintGen *irp, Stage1AirInstOptionalUnwrapPtr *instruction) {
1369 fprintf(irp->f, "&");
1370 ir_print_other_inst_gen(irp, instruction->base_ptr);
1371 fprintf(irp->f, ".*.?");
1372 if (!instruction->safety_check_on) {
1373 fprintf(irp->f, " // no safety");
1374 }
1375}
1376
1377static void ir_print_clz(IrPrintSrc *irp, Stage1ZirInstClz *instruction) {
1378 fprintf(irp->f, "@clz(");
1379 ir_print_other_inst_src(irp, instruction->type);
1380 fprintf(irp->f, ",");
1381 ir_print_other_inst_src(irp, instruction->op);
1382 fprintf(irp->f, ")");
1383}
1384
1385static void ir_print_clz(IrPrintGen *irp, Stage1AirInstClz *instruction) {
1386 fprintf(irp->f, "@clz(");
1387 ir_print_other_inst_gen(irp, instruction->op);
1388 fprintf(irp->f, ")");
1389}
1390
1391static void ir_print_ctz(IrPrintSrc *irp, Stage1ZirInstCtz *instruction) {
1392 fprintf(irp->f, "@ctz(");
1393 ir_print_other_inst_src(irp, instruction->type);
1394 fprintf(irp->f, ",");
1395 ir_print_other_inst_src(irp, instruction->op);
1396 fprintf(irp->f, ")");
1397}
1398
1399static void ir_print_ctz(IrPrintGen *irp, Stage1AirInstCtz *instruction) {
1400 fprintf(irp->f, "@ctz(");
1401 ir_print_other_inst_gen(irp, instruction->op);
1402 fprintf(irp->f, ")");
1403}
1404
1405static void ir_print_pop_count(IrPrintSrc *irp, Stage1ZirInstPopCount *instruction) {
1406 fprintf(irp->f, "@popCount(");
1407 ir_print_other_inst_src(irp, instruction->type);
1408 fprintf(irp->f, ",");
1409 ir_print_other_inst_src(irp, instruction->op);
1410 fprintf(irp->f, ")");
1411}
1412
1413static void ir_print_pop_count(IrPrintGen *irp, Stage1AirInstPopCount *instruction) {
1414 fprintf(irp->f, "@popCount(");
1415 ir_print_other_inst_gen(irp, instruction->op);
1416 fprintf(irp->f, ")");
1417}
1418
1419static void ir_print_bswap(IrPrintSrc *irp, Stage1ZirInstBswap *instruction) {
1420 fprintf(irp->f, "@byteSwap(");
1421 ir_print_other_inst_src(irp, instruction->type);
1422 fprintf(irp->f, ",");
1423 ir_print_other_inst_src(irp, instruction->op);
1424 fprintf(irp->f, ")");
1425}
1426
1427static void ir_print_bswap(IrPrintGen *irp, Stage1AirInstBswap *instruction) {
1428 fprintf(irp->f, "@byteSwap(");
1429 ir_print_other_inst_gen(irp, instruction->op);
1430 fprintf(irp->f, ")");
1431}
1432
1433static void ir_print_bit_reverse(IrPrintSrc *irp, Stage1ZirInstBitReverse *instruction) {
1434 fprintf(irp->f, "@bitReverse(");
1435 ir_print_other_inst_src(irp, instruction->type);
1436 fprintf(irp->f, ",");
1437 ir_print_other_inst_src(irp, instruction->op);
1438 fprintf(irp->f, ")");
1439}
1440
1441static void ir_print_bit_reverse(IrPrintGen *irp, Stage1AirInstBitReverse *instruction) {
1442 fprintf(irp->f, "@bitReverse(");
1443 ir_print_other_inst_gen(irp, instruction->op);
1444 fprintf(irp->f, ")");
1445}
1446
1447static void ir_print_switch_br(IrPrintSrc *irp, Stage1ZirInstSwitchBr *instruction) {
1448 fprintf(irp->f, "switch (");
1449 ir_print_other_inst_src(irp, instruction->target_value);
1450 fprintf(irp->f, ") ");
1451 for (size_t i = 0; i < instruction->case_count; i += 1) {
1452 Stage1ZirInstSwitchBrCase *this_case = &instruction->cases[i];
1453 ir_print_other_inst_src(irp, this_case->value);
1454 fprintf(irp->f, " => ");
1455 ir_print_other_block(irp, this_case->block);
1456 fprintf(irp->f, ", ");
1457 }
1458 fprintf(irp->f, "else => ");
1459 ir_print_other_block(irp, instruction->else_block);
1460 if (instruction->is_comptime != nullptr) {
1461 fprintf(irp->f, " // comptime = ");
1462 ir_print_other_inst_src(irp, instruction->is_comptime);
1463 }
1464}
1465
1466static void ir_print_switch_br(IrPrintGen *irp, Stage1AirInstSwitchBr *instruction) {
1467 fprintf(irp->f, "switch (");
1468 ir_print_other_inst_gen(irp, instruction->target_value);
1469 fprintf(irp->f, ") ");
1470 for (size_t i = 0; i < instruction->case_count; i += 1) {
1471 Stage1AirInstSwitchBrCase *this_case = &instruction->cases[i];
1472 ir_print_other_inst_gen(irp, this_case->value);
1473 fprintf(irp->f, " => ");
1474 ir_print_other_block_gen(irp, this_case->block);
1475 fprintf(irp->f, ", ");
1476 }
1477 fprintf(irp->f, "else => ");
1478 ir_print_other_block_gen(irp, instruction->else_block);
1479}
1480
1481static void ir_print_switch_var(IrPrintSrc *irp, Stage1ZirInstSwitchVar *instruction) {
1482 fprintf(irp->f, "switchvar ");
1483 ir_print_other_inst_src(irp, instruction->target_value_ptr);
1484 for (size_t i = 0; i < instruction->prongs_len; i += 1) {
1485 fprintf(irp->f, ", ");
1486 ir_print_other_inst_src(irp, instruction->prongs_ptr[i]);
1487 }
1488}
1489
1490static void ir_print_switch_else_var(IrPrintSrc *irp, Stage1ZirInstSwitchElseVar *instruction) {
1491 fprintf(irp->f, "switchelsevar ");
1492 ir_print_other_inst_src(irp, &instruction->switch_br->base);
1493}
1494
1495static void ir_print_switch_target(IrPrintSrc *irp, Stage1ZirInstSwitchTarget *instruction) {
1496 fprintf(irp->f, "switchtarget ");
1497 ir_print_other_inst_src(irp, instruction->target_value_ptr);
1498}
1499
1500static void ir_print_union_tag(IrPrintGen *irp, Stage1AirInstUnionTag *instruction) {
1501 fprintf(irp->f, "uniontag ");
1502 ir_print_other_inst_gen(irp, instruction->value);
1503}
1504
1505static void ir_print_import(IrPrintSrc *irp, Stage1ZirInstImport *instruction) {
1506 fprintf(irp->f, "@import(");
1507 ir_print_other_inst_src(irp, instruction->name);
1508 fprintf(irp->f, ")");
1509}
1510
1511static void ir_print_ref(IrPrintSrc *irp, Stage1ZirInstRef *instruction) {
1512 fprintf(irp->f, "ref ");
1513 ir_print_other_inst_src(irp, instruction->value);
1514}
1515
1516static void ir_print_ref_gen(IrPrintGen *irp, Stage1AirInstRef *instruction) {
1517 fprintf(irp->f, "@ref(");
1518 ir_print_other_inst_gen(irp, instruction->operand);
1519 fprintf(irp->f, ")result=");
1520 ir_print_other_inst_gen(irp, instruction->result_loc);
1521}
1522
1523static void ir_print_compile_err(IrPrintSrc *irp, Stage1ZirInstCompileErr *instruction) {
1524 fprintf(irp->f, "@compileError(");
1525 ir_print_other_inst_src(irp, instruction->msg);
1526 fprintf(irp->f, ")");
1527}
1528
1529static void ir_print_compile_log(IrPrintSrc *irp, Stage1ZirInstCompileLog *instruction) {
1530 fprintf(irp->f, "@compileLog(");
1531 for (size_t i = 0; i < instruction->msg_count; i += 1) {
1532 if (i != 0)
1533 fprintf(irp->f, ",");
1534 Stage1ZirInst *msg = instruction->msg_list[i];
1535 ir_print_other_inst_src(irp, msg);
1536 }
1537 fprintf(irp->f, ")");
1538}
1539
1540static void ir_print_err_name(IrPrintSrc *irp, Stage1ZirInstErrName *instruction) {
1541 fprintf(irp->f, "@errorName(");
1542 ir_print_other_inst_src(irp, instruction->value);
1543 fprintf(irp->f, ")");
1544}
1545
1546static void ir_print_err_name(IrPrintGen *irp, Stage1AirInstErrName *instruction) {
1547 fprintf(irp->f, "@errorName(");
1548 ir_print_other_inst_gen(irp, instruction->value);
1549 fprintf(irp->f, ")");
1550}
1551
1552static void ir_print_c_import(IrPrintSrc *irp, Stage1ZirInstCImport *instruction) {
1553 fprintf(irp->f, "@cImport(...)");
1554}
1555
1556static void ir_print_c_include(IrPrintSrc *irp, Stage1ZirInstCInclude *instruction) {
1557 fprintf(irp->f, "@cInclude(");
1558 ir_print_other_inst_src(irp, instruction->name);
1559 fprintf(irp->f, ")");
1560}
1561
1562static void ir_print_c_define(IrPrintSrc *irp, Stage1ZirInstCDefine *instruction) {
1563 fprintf(irp->f, "@cDefine(");
1564 ir_print_other_inst_src(irp, instruction->name);
1565 fprintf(irp->f, ", ");
1566 ir_print_other_inst_src(irp, instruction->value);
1567 fprintf(irp->f, ")");
1568}
1569
1570static void ir_print_c_undef(IrPrintSrc *irp, Stage1ZirInstCUndef *instruction) {
1571 fprintf(irp->f, "@cUndef(");
1572 ir_print_other_inst_src(irp, instruction->name);
1573 fprintf(irp->f, ")");
1574}
1575
1576static void ir_print_embed_file(IrPrintSrc *irp, Stage1ZirInstEmbedFile *instruction) {
1577 fprintf(irp->f, "@embedFile(");
1578 ir_print_other_inst_src(irp, instruction->name);
1579 fprintf(irp->f, ")");
1580}
1581
1582static void ir_print_cmpxchg_src(IrPrintSrc *irp, Stage1ZirInstCmpxchg *instruction) {
1583 fprintf(irp->f, "@cmpxchg(");
1584 ir_print_other_inst_src(irp, instruction->ptr);
1585 fprintf(irp->f, ", ");
1586 ir_print_other_inst_src(irp, instruction->cmp_value);
1587 fprintf(irp->f, ", ");
1588 ir_print_other_inst_src(irp, instruction->new_value);
1589 fprintf(irp->f, ", ");
1590 ir_print_other_inst_src(irp, instruction->success_order_value);
1591 fprintf(irp->f, ", ");
1592 ir_print_other_inst_src(irp, instruction->failure_order_value);
1593 fprintf(irp->f, ")result=");
1594 ir_print_result_loc(irp, instruction->result_loc);
1595}
1596
1597static void ir_print_cmpxchg_gen(IrPrintGen *irp, Stage1AirInstCmpxchg *instruction) {
1598 fprintf(irp->f, "@cmpxchg(");
1599 ir_print_other_inst_gen(irp, instruction->ptr);
1600 fprintf(irp->f, ", ");
1601 ir_print_other_inst_gen(irp, instruction->cmp_value);
1602 fprintf(irp->f, ", ");
1603 ir_print_other_inst_gen(irp, instruction->new_value);
1604 fprintf(irp->f, ", TODO print atomic orders)result=");
1605 ir_print_other_inst_gen(irp, instruction->result_loc);
1606}
1607
1608static void ir_print_fence(IrPrintSrc *irp, Stage1ZirInstFence *instruction) {
1609 fprintf(irp->f, "@fence(");
1610 ir_print_other_inst_src(irp, instruction->order);
1611 fprintf(irp->f, ")");
1612}
1613
1614static void ir_print_reduce(IrPrintSrc *irp, Stage1ZirInstReduce *instruction) {
1615 fprintf(irp->f, "@reduce(");
1616 ir_print_other_inst_src(irp, instruction->op);
1617 fprintf(irp->f, ", ");
1618 ir_print_other_inst_src(irp, instruction->value);
1619 fprintf(irp->f, ")");
1620}
1621
1622static const char *atomic_order_str(AtomicOrder order) {
1623 switch (order) {
1624 case AtomicOrderUnordered: return "Unordered";
1625 case AtomicOrderMonotonic: return "Monotonic";
1626 case AtomicOrderAcquire: return "Acquire";
1627 case AtomicOrderRelease: return "Release";
1628 case AtomicOrderAcqRel: return "AcqRel";
1629 case AtomicOrderSeqCst: return "SeqCst";
1630 }
1631 zig_unreachable();
1632}
1633
1634static void ir_print_fence(IrPrintGen *irp, Stage1AirInstFence *instruction) {
1635 fprintf(irp->f, "fence %s", atomic_order_str(instruction->order));
1636}
1637
1638static const char *reduce_op_str(ReduceOp op) {
1639 switch (op) {
1640 case ReduceOp_and: return "And";
1641 case ReduceOp_or: return "Or";
1642 case ReduceOp_xor: return "Xor";
1643 case ReduceOp_min: return "Min";
1644 case ReduceOp_max: return "Max";
1645 case ReduceOp_add: return "Add";
1646 case ReduceOp_mul: return "Mul";
1647 }
1648 zig_unreachable();
1649}
1650
1651static void ir_print_reduce(IrPrintGen *irp, Stage1AirInstReduce *instruction) {
1652 fprintf(irp->f, "@reduce(.%s, ", reduce_op_str(instruction->op));
1653 ir_print_other_inst_gen(irp, instruction->value);
1654 fprintf(irp->f, ")");
1655}
1656
1657static void ir_print_truncate(IrPrintSrc *irp, Stage1ZirInstTruncate *instruction) {
1658 fprintf(irp->f, "@truncate(");
1659 ir_print_other_inst_src(irp, instruction->dest_type);
1660 fprintf(irp->f, ", ");
1661 ir_print_other_inst_src(irp, instruction->target);
1662 fprintf(irp->f, ")");
1663}
1664
1665static void ir_print_truncate(IrPrintGen *irp, Stage1AirInstTruncate *instruction) {
1666 fprintf(irp->f, "@truncate(");
1667 ir_print_other_inst_gen(irp, instruction->target);
1668 fprintf(irp->f, ")");
1669}
1670
1671static void ir_print_int_cast(IrPrintSrc *irp, Stage1ZirInstIntCast *instruction) {
1672 fprintf(irp->f, "@intCast(");
1673 ir_print_other_inst_src(irp, instruction->dest_type);
1674 fprintf(irp->f, ", ");
1675 ir_print_other_inst_src(irp, instruction->target);
1676 fprintf(irp->f, ")");
1677}
1678
1679static void ir_print_float_cast(IrPrintSrc *irp, Stage1ZirInstFloatCast *instruction) {
1680 fprintf(irp->f, "@floatCast(");
1681 ir_print_other_inst_src(irp, instruction->dest_type);
1682 fprintf(irp->f, ", ");
1683 ir_print_other_inst_src(irp, instruction->target);
1684 fprintf(irp->f, ")");
1685}
1686
1687static void ir_print_err_set_cast(IrPrintSrc *irp, Stage1ZirInstErrSetCast *instruction) {
1688 fprintf(irp->f, "@errSetCast(");
1689 ir_print_other_inst_src(irp, instruction->dest_type);
1690 fprintf(irp->f, ", ");
1691 ir_print_other_inst_src(irp, instruction->target);
1692 fprintf(irp->f, ")");
1693}
1694
1695static void ir_print_int_to_float(IrPrintSrc *irp, Stage1ZirInstIntToFloat *instruction) {
1696 fprintf(irp->f, "@intToFloat(");
1697 ir_print_other_inst_src(irp, instruction->dest_type);
1698 fprintf(irp->f, ", ");
1699 ir_print_other_inst_src(irp, instruction->target);
1700 fprintf(irp->f, ")");
1701}
1702
1703static void ir_print_float_to_int(IrPrintSrc *irp, Stage1ZirInstFloatToInt *instruction) {
1704 fprintf(irp->f, "@floatToInt(");
1705 ir_print_other_inst_src(irp, instruction->dest_type);
1706 fprintf(irp->f, ", ");
1707 ir_print_other_inst_src(irp, instruction->target);
1708 fprintf(irp->f, ")");
1709}
1710
1711static void ir_print_bool_to_int(IrPrintSrc *irp, Stage1ZirInstBoolToInt *instruction) {
1712 fprintf(irp->f, "@boolToInt(");
1713 ir_print_other_inst_src(irp, instruction->target);
1714 fprintf(irp->f, ")");
1715}
1716
1717static void ir_print_vector_type(IrPrintSrc *irp, Stage1ZirInstVectorType *instruction) {
1718 fprintf(irp->f, "@Vector(");
1719 ir_print_other_inst_src(irp, instruction->len);
1720 fprintf(irp->f, ", ");
1721 ir_print_other_inst_src(irp, instruction->elem_type);
1722 fprintf(irp->f, ")");
1723}
1724
1725static void ir_print_shuffle_vector(IrPrintSrc *irp, Stage1ZirInstShuffleVector *instruction) {
1726 fprintf(irp->f, "@shuffle(");
1727 ir_print_other_inst_src(irp, instruction->scalar_type);
1728 fprintf(irp->f, ", ");
1729 ir_print_other_inst_src(irp, instruction->a);
1730 fprintf(irp->f, ", ");
1731 ir_print_other_inst_src(irp, instruction->b);
1732 fprintf(irp->f, ", ");
1733 ir_print_other_inst_src(irp, instruction->mask);
1734 fprintf(irp->f, ")");
1735}
1736
1737static void ir_print_shuffle_vector(IrPrintGen *irp, Stage1AirInstShuffleVector *instruction) {
1738 fprintf(irp->f, "@shuffle(");
1739 ir_print_other_inst_gen(irp, instruction->a);
1740 fprintf(irp->f, ", ");
1741 ir_print_other_inst_gen(irp, instruction->b);
1742 fprintf(irp->f, ", ");
1743 ir_print_other_inst_gen(irp, instruction->mask);
1744 fprintf(irp->f, ")");
1745}
1746
1747static void ir_print_select(IrPrintSrc *irp, Stage1ZirInstSelect *instruction) {
1748 fprintf(irp->f, "@select(");
1749 ir_print_other_inst_src(irp, instruction->scalar_type);
1750 fprintf(irp->f, ", ");
1751 ir_print_other_inst_src(irp, instruction->pred);
1752 fprintf(irp->f, ", ");
1753 ir_print_other_inst_src(irp, instruction->a);
1754 fprintf(irp->f, ", ");
1755 ir_print_other_inst_src(irp, instruction->b);
1756 fprintf(irp->f, ")");
1757}
1758
1759static void ir_print_select(IrPrintGen *irp, Stage1AirInstSelect *instruction) {
1760 fprintf(irp->f, "@select(");
1761 ir_print_other_inst_gen(irp, instruction->pred);
1762 fprintf(irp->f, ", ");
1763 ir_print_other_inst_gen(irp, instruction->a);
1764 fprintf(irp->f, ", ");
1765 ir_print_other_inst_gen(irp, instruction->b);
1766 fprintf(irp->f, ")");
1767}
1768
1769static void ir_print_splat_src(IrPrintSrc *irp, Stage1ZirInstSplat *instruction) {
1770 fprintf(irp->f, "@splat(");
1771 ir_print_other_inst_src(irp, instruction->len);
1772 fprintf(irp->f, ", ");
1773 ir_print_other_inst_src(irp, instruction->scalar);
1774 fprintf(irp->f, ")");
1775}
1776
1777static void ir_print_splat_gen(IrPrintGen *irp, Stage1AirInstSplat *instruction) {
1778 fprintf(irp->f, "@splat(");
1779 ir_print_other_inst_gen(irp, instruction->scalar);
1780 fprintf(irp->f, ")");
1781}
1782
1783static void ir_print_bool_not(IrPrintSrc *irp, Stage1ZirInstBoolNot *instruction) {
1784 fprintf(irp->f, "! ");
1785 ir_print_other_inst_src(irp, instruction->value);
1786}
1787
1788static void ir_print_bool_not(IrPrintGen *irp, Stage1AirInstBoolNot *instruction) {
1789 fprintf(irp->f, "! ");
1790 ir_print_other_inst_gen(irp, instruction->value);
1791}
1792
1793static void ir_print_wasm_memory_size(IrPrintSrc *irp, Stage1ZirInstWasmMemorySize *instruction) {
1794 fprintf(irp->f, "@wasmMemorySize(");
1795 ir_print_other_inst_src(irp, instruction->index);
1796 fprintf(irp->f, ")");
1797}
1798
1799static void ir_print_wasm_memory_size(IrPrintGen *irp, Stage1AirInstWasmMemorySize *instruction) {
1800 fprintf(irp->f, "@wasmMemorySize(");
1801 ir_print_other_inst_gen(irp, instruction->index);
1802 fprintf(irp->f, ")");
1803}
1804
1805static void ir_print_wasm_memory_grow(IrPrintSrc *irp, Stage1ZirInstWasmMemoryGrow *instruction) {
1806 fprintf(irp->f, "@wasmMemoryGrow(");
1807 ir_print_other_inst_src(irp, instruction->index);
1808 fprintf(irp->f, ", ");
1809 ir_print_other_inst_src(irp, instruction->delta);
1810 fprintf(irp->f, ")");
1811}
1812
1813static void ir_print_wasm_memory_grow(IrPrintGen *irp, Stage1AirInstWasmMemoryGrow *instruction) {
1814 fprintf(irp->f, "@wasmMemoryGrow(");
1815 ir_print_other_inst_gen(irp, instruction->index);
1816 fprintf(irp->f, ", ");
1817 ir_print_other_inst_gen(irp, instruction->delta);
1818 fprintf(irp->f, ")");
1819}
1820
1821static void ir_print_builtin_src(IrPrintSrc *irp, Stage1ZirInstSrc *instruction) {
1822 fprintf(irp->f, "@src()");
1823}
1824
1825static void ir_print_memset(IrPrintSrc *irp, Stage1ZirInstMemset *instruction) {
1826 fprintf(irp->f, "@memset(");
1827 ir_print_other_inst_src(irp, instruction->dest_ptr);
1828 fprintf(irp->f, ", ");
1829 ir_print_other_inst_src(irp, instruction->byte);
1830 fprintf(irp->f, ", ");
1831 ir_print_other_inst_src(irp, instruction->count);
1832 fprintf(irp->f, ")");
1833}
1834
1835static void ir_print_memset(IrPrintGen *irp, Stage1AirInstMemset *instruction) {
1836 fprintf(irp->f, "@memset(");
1837 ir_print_other_inst_gen(irp, instruction->dest_ptr);
1838 fprintf(irp->f, ", ");
1839 ir_print_other_inst_gen(irp, instruction->byte);
1840 fprintf(irp->f, ", ");
1841 ir_print_other_inst_gen(irp, instruction->count);
1842 fprintf(irp->f, ")");
1843}
1844
1845static void ir_print_memcpy(IrPrintSrc *irp, Stage1ZirInstMemcpy *instruction) {
1846 fprintf(irp->f, "@memcpy(");
1847 ir_print_other_inst_src(irp, instruction->dest_ptr);
1848 fprintf(irp->f, ", ");
1849 ir_print_other_inst_src(irp, instruction->src_ptr);
1850 fprintf(irp->f, ", ");
1851 ir_print_other_inst_src(irp, instruction->count);
1852 fprintf(irp->f, ")");
1853}
1854
1855static void ir_print_memcpy(IrPrintGen *irp, Stage1AirInstMemcpy *instruction) {
1856 fprintf(irp->f, "@memcpy(");
1857 ir_print_other_inst_gen(irp, instruction->dest_ptr);
1858 fprintf(irp->f, ", ");
1859 ir_print_other_inst_gen(irp, instruction->src_ptr);
1860 fprintf(irp->f, ", ");
1861 ir_print_other_inst_gen(irp, instruction->count);
1862 fprintf(irp->f, ")");
1863}
1864
1865static void ir_print_slice_src(IrPrintSrc *irp, Stage1ZirInstSlice *instruction) {
1866 ir_print_other_inst_src(irp, instruction->ptr);
1867 fprintf(irp->f, "[");
1868 ir_print_other_inst_src(irp, instruction->start);
1869 fprintf(irp->f, "..");
1870 if (instruction->end)
1871 ir_print_other_inst_src(irp, instruction->end);
1872 fprintf(irp->f, "]result=");
1873 ir_print_result_loc(irp, instruction->result_loc);
1874}
1875
1876static void ir_print_slice_gen(IrPrintGen *irp, Stage1AirInstSlice *instruction) {
1877 ir_print_other_inst_gen(irp, instruction->ptr);
1878 fprintf(irp->f, "[");
1879 ir_print_other_inst_gen(irp, instruction->start);
1880 fprintf(irp->f, "..");
1881 if (instruction->end)
1882 ir_print_other_inst_gen(irp, instruction->end);
1883 fprintf(irp->f, "]result=");
1884 ir_print_other_inst_gen(irp, instruction->result_loc);
1885}
1886
1887static void ir_print_breakpoint(IrPrintSrc *irp, Stage1ZirInstBreakpoint *instruction) {
1888 fprintf(irp->f, "@breakpoint()");
1889}
1890
1891static void ir_print_breakpoint(IrPrintGen *irp, Stage1AirInstBreakpoint *instruction) {
1892 fprintf(irp->f, "@breakpoint()");
1893}
1894
1895static void ir_print_frame_address(IrPrintSrc *irp, Stage1ZirInstFrameAddress *instruction) {
1896 fprintf(irp->f, "@frameAddress()");
1897}
1898
1899static void ir_print_frame_address(IrPrintGen *irp, Stage1AirInstFrameAddress *instruction) {
1900 fprintf(irp->f, "@frameAddress()");
1901}
1902
1903static void ir_print_handle(IrPrintSrc *irp, Stage1ZirInstFrameHandle *instruction) {
1904 fprintf(irp->f, "@frame()");
1905}
1906
1907static void ir_print_handle(IrPrintGen *irp, Stage1AirInstFrameHandle *instruction) {
1908 fprintf(irp->f, "@frame()");
1909}
1910
1911static void ir_print_frame_type(IrPrintSrc *irp, Stage1ZirInstFrameType *instruction) {
1912 fprintf(irp->f, "@Frame(");
1913 ir_print_other_inst_src(irp, instruction->fn);
1914 fprintf(irp->f, ")");
1915}
1916
1917static void ir_print_frame_size_src(IrPrintSrc *irp, Stage1ZirInstFrameSize *instruction) {
1918 fprintf(irp->f, "@frameSize(");
1919 ir_print_other_inst_src(irp, instruction->fn);
1920 fprintf(irp->f, ")");
1921}
1922
1923static void ir_print_frame_size_gen(IrPrintGen *irp, Stage1AirInstFrameSize *instruction) {
1924 fprintf(irp->f, "@frameSize(");
1925 ir_print_other_inst_gen(irp, instruction->fn);
1926 fprintf(irp->f, ")");
1927}
1928
1929static void ir_print_return_address(IrPrintSrc *irp, Stage1ZirInstReturnAddress *instruction) {
1930 fprintf(irp->f, "@returnAddress()");
1931}
1932
1933static void ir_print_return_address(IrPrintGen *irp, Stage1AirInstReturnAddress *instruction) {
1934 fprintf(irp->f, "@returnAddress()");
1935}
1936
1937static void ir_print_align_of(IrPrintSrc *irp, Stage1ZirInstAlignOf *instruction) {
1938 fprintf(irp->f, "@alignOf(");
1939 ir_print_other_inst_src(irp, instruction->type_value);
1940 fprintf(irp->f, ")");
1941}
1942
1943static void ir_print_overflow_op(IrPrintSrc *irp, Stage1ZirInstOverflowOp *instruction) {
1944 switch (instruction->op) {
1945 case IrOverflowOpAdd:
1946 fprintf(irp->f, "@addWithOverflow(");
1947 break;
1948 case IrOverflowOpSub:
1949 fprintf(irp->f, "@subWithOverflow(");
1950 break;
1951 case IrOverflowOpMul:
1952 fprintf(irp->f, "@mulWithOverflow(");
1953 break;
1954 case IrOverflowOpShl:
1955 fprintf(irp->f, "@shlWithOverflow(");
1956 break;
1957 }
1958 ir_print_other_inst_src(irp, instruction->type_value);
1959 fprintf(irp->f, ", ");
1960 ir_print_other_inst_src(irp, instruction->op1);
1961 fprintf(irp->f, ", ");
1962 ir_print_other_inst_src(irp, instruction->op2);
1963 fprintf(irp->f, ", ");
1964 ir_print_other_inst_src(irp, instruction->result_ptr);
1965 fprintf(irp->f, ")");
1966}
1967
1968static void ir_print_overflow_op(IrPrintGen *irp, Stage1AirInstOverflowOp *instruction) {
1969 switch (instruction->op) {
1970 case IrOverflowOpAdd:
1971 fprintf(irp->f, "@addWithOverflow(");
1972 break;
1973 case IrOverflowOpSub:
1974 fprintf(irp->f, "@subWithOverflow(");
1975 break;
1976 case IrOverflowOpMul:
1977 fprintf(irp->f, "@mulWithOverflow(");
1978 break;
1979 case IrOverflowOpShl:
1980 fprintf(irp->f, "@shlWithOverflow(");
1981 break;
1982 }
1983 ir_print_other_inst_gen(irp, instruction->op1);
1984 fprintf(irp->f, ", ");
1985 ir_print_other_inst_gen(irp, instruction->op2);
1986 fprintf(irp->f, ", ");
1987 ir_print_other_inst_gen(irp, instruction->result_ptr);
1988 fprintf(irp->f, ")");
1989}
1990
1991static void ir_print_test_err_src(IrPrintSrc *irp, Stage1ZirInstTestErr *instruction) {
1992 fprintf(irp->f, "@testError(");
1993 ir_print_other_inst_src(irp, instruction->base_ptr);
1994 fprintf(irp->f, ")");
1995}
1996
1997static void ir_print_test_err_gen(IrPrintGen *irp, Stage1AirInstTestErr *instruction) {
1998 fprintf(irp->f, "@testError(");
1999 ir_print_other_inst_gen(irp, instruction->err_union);
2000 fprintf(irp->f, ")");
2001}
2002
2003static void ir_print_unwrap_err_code(IrPrintSrc *irp, Stage1ZirInstUnwrapErrCode *instruction) {
2004 fprintf(irp->f, "UnwrapErrorCode(");
2005 ir_print_other_inst_src(irp, instruction->err_union_ptr);
2006 fprintf(irp->f, ")");
2007}
2008
2009static void ir_print_unwrap_err_code(IrPrintGen *irp, Stage1AirInstUnwrapErrCode *instruction) {
2010 fprintf(irp->f, "UnwrapErrorCode(");
2011 ir_print_other_inst_gen(irp, instruction->err_union_ptr);
2012 fprintf(irp->f, ")");
2013}
2014
2015static void ir_print_unwrap_err_payload(IrPrintSrc *irp, Stage1ZirInstUnwrapErrPayload *instruction) {
2016 fprintf(irp->f, "ErrorUnionFieldPayload(");
2017 ir_print_other_inst_src(irp, instruction->value);
2018 fprintf(irp->f, ")safety=%d,init=%d",instruction->safety_check_on, instruction->initializing);
2019}
2020
2021static void ir_print_unwrap_err_payload(IrPrintGen *irp, Stage1AirInstUnwrapErrPayload *instruction) {
2022 fprintf(irp->f, "ErrorUnionFieldPayload(");
2023 ir_print_other_inst_gen(irp, instruction->value);
2024 fprintf(irp->f, ")safety=%d,init=%d",instruction->safety_check_on, instruction->initializing);
2025}
2026
2027static void ir_print_optional_wrap(IrPrintGen *irp, Stage1AirInstOptionalWrap *instruction) {
2028 fprintf(irp->f, "@optionalWrap(");
2029 ir_print_other_inst_gen(irp, instruction->operand);
2030 fprintf(irp->f, ")result=");
2031 ir_print_other_inst_gen(irp, instruction->result_loc);
2032}
2033
2034static void ir_print_err_wrap_code(IrPrintGen *irp, Stage1AirInstErrWrapCode *instruction) {
2035 fprintf(irp->f, "@errWrapCode(");
2036 ir_print_other_inst_gen(irp, instruction->operand);
2037 fprintf(irp->f, ")result=");
2038 ir_print_other_inst_gen(irp, instruction->result_loc);
2039}
2040
2041static void ir_print_err_wrap_payload(IrPrintGen *irp, Stage1AirInstErrWrapPayload *instruction) {
2042 fprintf(irp->f, "@errWrapPayload(");
2043 ir_print_other_inst_gen(irp, instruction->operand);
2044 fprintf(irp->f, ")result=");
2045 ir_print_other_inst_gen(irp, instruction->result_loc);
2046}
2047
2048static void ir_print_fn_proto(IrPrintSrc *irp, Stage1ZirInstFnProto *instruction) {
2049 fprintf(irp->f, "fn(");
2050 for (size_t i = 0; i < instruction->base.source_node->data.fn_proto.params.length; i += 1) {
2051 if (i != 0)
2052 fprintf(irp->f, ",");
2053 if (instruction->is_var_args && i == instruction->base.source_node->data.fn_proto.params.length - 1) {
2054 fprintf(irp->f, "...");
2055 } else {
2056 ir_print_other_inst_src(irp, instruction->param_types[i]);
2057 }
2058 }
2059 fprintf(irp->f, ")");
2060 if (instruction->align_value != nullptr) {
2061 fprintf(irp->f, " align ");
2062 ir_print_other_inst_src(irp, instruction->align_value);
2063 fprintf(irp->f, " ");
2064 }
2065 fprintf(irp->f, "->");
2066 ir_print_other_inst_src(irp, instruction->return_type);
2067}
2068
2069static void ir_print_test_comptime(IrPrintSrc *irp, Stage1ZirInstTestComptime *instruction) {
2070 fprintf(irp->f, "@testComptime(");
2071 ir_print_other_inst_src(irp, instruction->value);
2072 fprintf(irp->f, ")");
2073}
2074
2075static void ir_print_ptr_cast_src(IrPrintSrc *irp, Stage1ZirInstPtrCast *instruction) {
2076 fprintf(irp->f, "@ptrCast(");
2077 if (instruction->dest_type) {
2078 ir_print_other_inst_src(irp, instruction->dest_type);
2079 }
2080 fprintf(irp->f, ",");
2081 ir_print_other_inst_src(irp, instruction->ptr);
2082 fprintf(irp->f, ")");
2083}
2084
2085static void ir_print_ptr_cast_gen(IrPrintGen *irp, Stage1AirInstPtrCast *instruction) {
2086 fprintf(irp->f, "@ptrCast(");
2087 ir_print_other_inst_gen(irp, instruction->ptr);
2088 fprintf(irp->f, ")");
2089}
2090
2091static void ir_print_implicit_cast(IrPrintSrc *irp, Stage1ZirInstImplicitCast *instruction) {
2092 fprintf(irp->f, "@implicitCast(");
2093 ir_print_other_inst_src(irp, instruction->operand);
2094 fprintf(irp->f, ")result=");
2095 ir_print_result_loc(irp, &instruction->result_loc_cast->base);
2096}
2097
2098static void ir_print_bit_cast_src(IrPrintSrc *irp, Stage1ZirInstBitCast *instruction) {
2099 fprintf(irp->f, "@bitCast(");
2100 ir_print_other_inst_src(irp, instruction->operand);
2101 fprintf(irp->f, ")result=");
2102 ir_print_result_loc(irp, &instruction->result_loc_bit_cast->base);
2103}
2104
2105static void ir_print_bit_cast_gen(IrPrintGen *irp, Stage1AirInstBitCast *instruction) {
2106 fprintf(irp->f, "@bitCast(");
2107 ir_print_other_inst_gen(irp, instruction->operand);
2108 fprintf(irp->f, ")");
2109}
2110
2111static void ir_print_widen_or_shorten(IrPrintGen *irp, Stage1AirInstWidenOrShorten *instruction) {
2112 fprintf(irp->f, "WidenOrShorten(");
2113 ir_print_other_inst_gen(irp, instruction->target);
2114 fprintf(irp->f, ")");
2115}
2116
2117static void ir_print_ptr_to_int(IrPrintSrc *irp, Stage1ZirInstPtrToInt *instruction) {
2118 fprintf(irp->f, "@ptrToInt(");
2119 ir_print_other_inst_src(irp, instruction->target);
2120 fprintf(irp->f, ")");
2121}
2122
2123static void ir_print_ptr_to_int(IrPrintGen *irp, Stage1AirInstPtrToInt *instruction) {
2124 fprintf(irp->f, "@ptrToInt(");
2125 ir_print_other_inst_gen(irp, instruction->target);
2126 fprintf(irp->f, ")");
2127}
2128
2129static void ir_print_int_to_ptr(IrPrintSrc *irp, Stage1ZirInstIntToPtr *instruction) {
2130 fprintf(irp->f, "@intToPtr(");
2131 ir_print_other_inst_src(irp, instruction->dest_type);
2132 fprintf(irp->f, ",");
2133 ir_print_other_inst_src(irp, instruction->target);
2134 fprintf(irp->f, ")");
2135}
2136
2137static void ir_print_int_to_ptr(IrPrintGen *irp, Stage1AirInstIntToPtr *instruction) {
2138 fprintf(irp->f, "@intToPtr(");
2139 ir_print_other_inst_gen(irp, instruction->target);
2140 fprintf(irp->f, ")");
2141}
2142
2143static void ir_print_int_to_enum(IrPrintSrc *irp, Stage1ZirInstIntToEnum *instruction) {
2144 fprintf(irp->f, "@intToEnum(");
2145 ir_print_other_inst_src(irp, instruction->dest_type);
2146 fprintf(irp->f, ",");
2147 ir_print_other_inst_src(irp, instruction->target);
2148 fprintf(irp->f, ")");
2149}
2150
2151static void ir_print_int_to_enum(IrPrintGen *irp, Stage1AirInstIntToEnum *instruction) {
2152 fprintf(irp->f, "@intToEnum(");
2153 ir_print_other_inst_gen(irp, instruction->target);
2154 fprintf(irp->f, ")");
2155}
2156
2157static void ir_print_enum_to_int(IrPrintSrc *irp, Stage1ZirInstEnumToInt *instruction) {
2158 fprintf(irp->f, "@enumToInt(");
2159 ir_print_other_inst_src(irp, instruction->target);
2160 fprintf(irp->f, ")");
2161}
2162
2163static void ir_print_check_runtime_scope(IrPrintSrc *irp, Stage1ZirInstCheckRuntimeScope *instruction) {
2164 fprintf(irp->f, "@checkRuntimeScope(");
2165 ir_print_other_inst_src(irp, instruction->scope_is_comptime);
2166 fprintf(irp->f, ",");
2167 ir_print_other_inst_src(irp, instruction->is_comptime);
2168 fprintf(irp->f, ")");
2169}
2170
2171static void ir_print_array_to_vector(IrPrintGen *irp, Stage1AirInstArrayToVector *instruction) {
2172 fprintf(irp->f, "ArrayToVector(");
2173 ir_print_other_inst_gen(irp, instruction->array);
2174 fprintf(irp->f, ")");
2175}
2176
2177static void ir_print_vector_to_array(IrPrintGen *irp, Stage1AirInstVectorToArray *instruction) {
2178 fprintf(irp->f, "VectorToArray(");
2179 ir_print_other_inst_gen(irp, instruction->vector);
2180 fprintf(irp->f, ")result=");
2181 ir_print_other_inst_gen(irp, instruction->result_loc);
2182}
2183
2184static void ir_print_ptr_of_array_to_slice(IrPrintGen *irp, Stage1AirInstPtrOfArrayToSlice *instruction) {
2185 fprintf(irp->f, "PtrOfArrayToSlice(");
2186 ir_print_other_inst_gen(irp, instruction->operand);
2187 fprintf(irp->f, ")result=");
2188 ir_print_other_inst_gen(irp, instruction->result_loc);
2189}
2190
2191static void ir_print_assert_zero(IrPrintGen *irp, Stage1AirInstAssertZero *instruction) {
2192 fprintf(irp->f, "AssertZero(");
2193 ir_print_other_inst_gen(irp, instruction->target);
2194 fprintf(irp->f, ")");
2195}
2196
2197static void ir_print_assert_non_null(IrPrintGen *irp, Stage1AirInstAssertNonNull *instruction) {
2198 fprintf(irp->f, "AssertNonNull(");
2199 ir_print_other_inst_gen(irp, instruction->target);
2200 fprintf(irp->f, ")");
2201}
2202
2203static void ir_print_alloca_src(IrPrintSrc *irp, Stage1ZirInstAlloca *instruction) {
2204 fprintf(irp->f, "Alloca(align=");
2205 ir_print_other_inst_src(irp, instruction->align);
2206 fprintf(irp->f, ",name=%s)", instruction->name_hint);
2207}
2208
2209static void ir_print_alloca_gen(IrPrintGen *irp, Stage1AirInstAlloca *instruction) {
2210 fprintf(irp->f, "Alloca(align=%" PRIu32 ",name=%s)", instruction->align, instruction->name_hint);
2211}
2212
2213static void ir_print_end_expr(IrPrintSrc *irp, Stage1ZirInstEndExpr *instruction) {
2214 fprintf(irp->f, "EndExpr(result=");
2215 ir_print_result_loc(irp, instruction->result_loc);
2216 fprintf(irp->f, ",value=");
2217 ir_print_other_inst_src(irp, instruction->value);
2218 fprintf(irp->f, ")");
2219}
2220
2221static void ir_print_int_to_err(IrPrintSrc *irp, Stage1ZirInstIntToErr *instruction) {
2222 fprintf(irp->f, "inttoerr ");
2223 ir_print_other_inst_src(irp, instruction->target);
2224}
2225
2226static void ir_print_int_to_err(IrPrintGen *irp, Stage1AirInstIntToErr *instruction) {
2227 fprintf(irp->f, "inttoerr ");
2228 ir_print_other_inst_gen(irp, instruction->target);
2229}
2230
2231static void ir_print_err_to_int(IrPrintSrc *irp, Stage1ZirInstErrToInt *instruction) {
2232 fprintf(irp->f, "errtoint ");
2233 ir_print_other_inst_src(irp, instruction->target);
2234}
2235
2236static void ir_print_err_to_int(IrPrintGen *irp, Stage1AirInstErrToInt *instruction) {
2237 fprintf(irp->f, "errtoint ");
2238 ir_print_other_inst_gen(irp, instruction->target);
2239}
2240
2241static void ir_print_check_switch_prongs(IrPrintSrc *irp, Stage1ZirInstCheckSwitchProngs *instruction,
2242 bool have_underscore_prong)
2243{
2244 fprintf(irp->f, "@checkSwitchProngs(");
2245 ir_print_other_inst_src(irp, instruction->target_value);
2246 fprintf(irp->f, ",");
2247 for (size_t i = 0; i < instruction->range_count; i += 1) {
2248 if (i != 0)
2249 fprintf(irp->f, ",");
2250 ir_print_other_inst_src(irp, instruction->ranges[i].start);
2251 fprintf(irp->f, "...");
2252 ir_print_other_inst_src(irp, instruction->ranges[i].end);
2253 }
2254 const char *have_else_str = instruction->else_prong != nullptr ? "yes" : "no";
2255 fprintf(irp->f, ")else:%s", have_else_str);
2256 const char *have_under_str = have_underscore_prong ? "yes" : "no";
2257 fprintf(irp->f, " _:%s", have_under_str);
2258}
2259
2260static void ir_print_check_statement_is_void(IrPrintSrc *irp, Stage1ZirInstCheckStatementIsVoid *instruction) {
2261 fprintf(irp->f, "@checkStatementIsVoid(");
2262 ir_print_other_inst_src(irp, instruction->statement_value);
2263 fprintf(irp->f, ")");
2264}
2265
2266static void ir_print_type_name(IrPrintSrc *irp, Stage1ZirInstTypeName *instruction) {
2267 fprintf(irp->f, "typename ");
2268 ir_print_other_inst_src(irp, instruction->type_value);
2269}
2270
2271static void ir_print_tag_name(IrPrintSrc *irp, Stage1ZirInstTagName *instruction) {
2272 fprintf(irp->f, "tagname ");
2273 ir_print_other_inst_src(irp, instruction->target);
2274}
2275
2276static void ir_print_tag_name(IrPrintGen *irp, Stage1AirInstTagName *instruction) {
2277 fprintf(irp->f, "tagname ");
2278 ir_print_other_inst_gen(irp, instruction->target);
2279}
2280
2281static void ir_print_ptr_type(IrPrintSrc *irp, Stage1ZirInstPtrType *instruction) {
2282 fprintf(irp->f, "&");
2283 if (instruction->align_value != nullptr) {
2284 fprintf(irp->f, "align(");
2285 ir_print_other_inst_src(irp, instruction->align_value);
2286 fprintf(irp->f, ")");
2287 }
2288 const char *const_str = instruction->is_const ? "const " : "";
2289 const char *volatile_str = instruction->is_volatile ? "volatile " : "";
2290 fprintf(irp->f, ":%" PRIu32 ":%" PRIu32 " %s%s", instruction->bit_offset_start, instruction->host_int_bytes,
2291 const_str, volatile_str);
2292 ir_print_other_inst_src(irp, instruction->child_type);
2293}
2294
2295static void ir_print_ptr_type_simple(IrPrintSrc *irp, Stage1ZirInstPtrTypeSimple *instruction,
2296 bool is_const)
2297{
2298 fprintf(irp->f, "&");
2299 const char *const_str = is_const ? "const " : "";
2300 fprintf(irp->f, "*%s", const_str);
2301 ir_print_other_inst_src(irp, instruction->child_type);
2302}
2303
2304static void ir_print_decl_ref(IrPrintSrc *irp, Stage1ZirInstDeclRef *instruction) {
2305 const char *ptr_str = (instruction->lval != LValNone) ? "ptr " : "";
2306 fprintf(irp->f, "declref %s%s", ptr_str, buf_ptr(instruction->tld->name));
2307}
2308
2309static void ir_print_panic(IrPrintSrc *irp, Stage1ZirInstPanic *instruction) {
2310 fprintf(irp->f, "@panic(");
2311 ir_print_other_inst_src(irp, instruction->msg);
2312 fprintf(irp->f, ")");
2313}
2314
2315static void ir_print_panic(IrPrintGen *irp, Stage1AirInstPanic *instruction) {
2316 fprintf(irp->f, "@panic(");
2317 ir_print_other_inst_gen(irp, instruction->msg);
2318 fprintf(irp->f, ")");
2319}
2320
2321static void ir_print_field_parent_ptr(IrPrintSrc *irp, Stage1ZirInstFieldParentPtr *instruction) {
2322 fprintf(irp->f, "@fieldParentPtr(");
2323 ir_print_other_inst_src(irp, instruction->type_value);
2324 fprintf(irp->f, ",");
2325 ir_print_other_inst_src(irp, instruction->field_name);
2326 fprintf(irp->f, ",");
2327 ir_print_other_inst_src(irp, instruction->field_ptr);
2328 fprintf(irp->f, ")");
2329}
2330
2331static void ir_print_field_parent_ptr(IrPrintGen *irp, Stage1AirInstFieldParentPtr *instruction) {
2332 fprintf(irp->f, "@fieldParentPtr(%s,", buf_ptr(instruction->field->name));
2333 ir_print_other_inst_gen(irp, instruction->field_ptr);
2334 fprintf(irp->f, ")");
2335}
2336
2337static void ir_print_offset_of(IrPrintSrc *irp, Stage1ZirInstOffsetOf *instruction) {
2338 fprintf(irp->f, "@offset_of(");
2339 ir_print_other_inst_src(irp, instruction->type_value);
2340 fprintf(irp->f, ",");
2341 ir_print_other_inst_src(irp, instruction->field_name);
2342 fprintf(irp->f, ")");
2343}
2344
2345static void ir_print_bit_offset_of(IrPrintSrc *irp, Stage1ZirInstBitOffsetOf *instruction) {
2346 fprintf(irp->f, "@bit_offset_of(");
2347 ir_print_other_inst_src(irp, instruction->type_value);
2348 fprintf(irp->f, ",");
2349 ir_print_other_inst_src(irp, instruction->field_name);
2350 fprintf(irp->f, ")");
2351}
2352
2353static void ir_print_type_info(IrPrintSrc *irp, Stage1ZirInstTypeInfo *instruction) {
2354 fprintf(irp->f, "@typeInfo(");
2355 ir_print_other_inst_src(irp, instruction->type_value);
2356 fprintf(irp->f, ")");
2357}
2358
2359static void ir_print_type(IrPrintSrc *irp, Stage1ZirInstType *instruction) {
2360 fprintf(irp->f, "@Type(");
2361 ir_print_other_inst_src(irp, instruction->type_info);
2362 fprintf(irp->f, ")");
2363}
2364
2365static void ir_print_has_field(IrPrintSrc *irp, Stage1ZirInstHasField *instruction) {
2366 fprintf(irp->f, "@hasField(");
2367 ir_print_other_inst_src(irp, instruction->container_type);
2368 fprintf(irp->f, ",");
2369 ir_print_other_inst_src(irp, instruction->field_name);
2370 fprintf(irp->f, ")");
2371}
2372
2373static void ir_print_set_eval_branch_quota(IrPrintSrc *irp, Stage1ZirInstSetEvalBranchQuota *instruction) {
2374 fprintf(irp->f, "@setEvalBranchQuota(");
2375 ir_print_other_inst_src(irp, instruction->new_quota);
2376 fprintf(irp->f, ")");
2377}
2378
2379static void ir_print_align_cast(IrPrintSrc *irp, Stage1ZirInstAlignCast *instruction) {
2380 fprintf(irp->f, "@alignCast(");
2381 ir_print_other_inst_src(irp, instruction->align_bytes);
2382 fprintf(irp->f, ",");
2383 ir_print_other_inst_src(irp, instruction->target);
2384 fprintf(irp->f, ")");
2385}
2386
2387static void ir_print_addrspace_cast(IrPrintSrc *irp, Stage1ZirInstAddrSpaceCast *instruction) {
2388 fprintf(irp->f, "@addrSpaceCast(");
2389 ir_print_other_inst_src(irp, instruction->addrspace);
2390 fprintf(irp->f, ",");
2391 ir_print_other_inst_src(irp, instruction->ptr);
2392 fprintf(irp->f, ")");
2393}
2394
2395static void ir_print_align_cast(IrPrintGen *irp, Stage1AirInstAlignCast *instruction) {
2396 fprintf(irp->f, "@alignCast(");
2397 ir_print_other_inst_gen(irp, instruction->target);
2398 fprintf(irp->f, ")");
2399}
2400
2401static void ir_print_resolve_result(IrPrintSrc *irp, Stage1ZirInstResolveResult *instruction) {
2402 fprintf(irp->f, "ResolveResult(");
2403 ir_print_result_loc(irp, instruction->result_loc);
2404 fprintf(irp->f, ")");
2405}
2406
2407static void ir_print_reset_result(IrPrintSrc *irp, Stage1ZirInstResetResult *instruction) {
2408 fprintf(irp->f, "ResetResult(");
2409 ir_print_result_loc(irp, instruction->result_loc);
2410 fprintf(irp->f, ")");
2411}
2412
2413static void ir_print_set_align_stack(IrPrintSrc *irp, Stage1ZirInstSetAlignStack *instruction) {
2414 fprintf(irp->f, "@setAlignStack(");
2415 ir_print_other_inst_src(irp, instruction->align_bytes);
2416 fprintf(irp->f, ")");
2417}
2418
2419static void ir_print_arg_type(IrPrintSrc *irp, Stage1ZirInstArgType *instruction, bool allow_var) {
2420 fprintf(irp->f, "@ArgType(");
2421 ir_print_other_inst_src(irp, instruction->fn_type);
2422 fprintf(irp->f, ",");
2423 ir_print_other_inst_src(irp, instruction->arg_index);
2424 fprintf(irp->f, ",");
2425 if (allow_var) {
2426 fprintf(irp->f, "allow_var=true");
2427 } else {
2428 fprintf(irp->f, "allow_var=false");
2429 }
2430 fprintf(irp->f, ")");
2431}
2432
2433static void ir_print_export(IrPrintSrc *irp, Stage1ZirInstExport *instruction) {
2434 fprintf(irp->f, "@export(");
2435 ir_print_other_inst_src(irp, instruction->target);
2436 fprintf(irp->f, ",");
2437 ir_print_other_inst_src(irp, instruction->options);
2438 fprintf(irp->f, ")");
2439}
2440
2441static void ir_print_extern(IrPrintGen *irp, Stage1AirInstExtern *instruction) {
2442 fprintf(irp->f, "@extern(...)");
2443}
2444
2445static void ir_print_extern(IrPrintSrc *irp, Stage1ZirInstExtern *instruction) {
2446 fprintf(irp->f, "@extern(");
2447 ir_print_other_inst_src(irp, instruction->type);
2448 fprintf(irp->f, ",");
2449 ir_print_other_inst_src(irp, instruction->options);
2450 fprintf(irp->f, ")");
2451}
2452
2453static void ir_print_prefetch(IrPrintSrc *irp, Stage1ZirInstPrefetch *instruction) {
2454 fprintf(irp->f, "@prefetch(");
2455 ir_print_other_inst_src(irp, instruction->ptr);
2456 fprintf(irp->f, ",");
2457 ir_print_other_inst_src(irp, instruction->options);
2458 fprintf(irp->f, ")");
2459}
2460
2461static void ir_print_prefetch(IrPrintGen *irp, Stage1AirInstPrefetch *instruction) {
2462 fprintf(irp->f, "@prefetch(...)");
2463}
2464
2465static void ir_print_error_return_trace(IrPrintSrc *irp, Stage1ZirInstErrorReturnTrace *instruction) {
2466 fprintf(irp->f, "@errorReturnTrace(");
2467 switch (instruction->optional) {
2468 case IrInstErrorReturnTraceNull:
2469 fprintf(irp->f, "Null");
2470 break;
2471 case IrInstErrorReturnTraceNonNull:
2472 fprintf(irp->f, "NonNull");
2473 break;
2474 }
2475 fprintf(irp->f, ")");
2476}
2477
2478static void ir_print_error_return_trace(IrPrintGen *irp, Stage1AirInstErrorReturnTrace *instruction) {
2479 fprintf(irp->f, "@errorReturnTrace(");
2480 switch (instruction->optional) {
2481 case IrInstErrorReturnTraceNull:
2482 fprintf(irp->f, "Null");
2483 break;
2484 case IrInstErrorReturnTraceNonNull:
2485 fprintf(irp->f, "NonNull");
2486 break;
2487 }
2488 fprintf(irp->f, ")");
2489}
2490
2491static void ir_print_error_union(IrPrintSrc *irp, Stage1ZirInstErrorUnion *instruction) {
2492 ir_print_other_inst_src(irp, instruction->err_set);
2493 fprintf(irp->f, "!");
2494 ir_print_other_inst_src(irp, instruction->payload);
2495}
2496
2497static void ir_print_atomic_rmw(IrPrintSrc *irp, Stage1ZirInstAtomicRmw *instruction) {
2498 fprintf(irp->f, "@atomicRmw(");
2499 ir_print_other_inst_src(irp, instruction->operand_type);
2500 fprintf(irp->f, ",");
2501 ir_print_other_inst_src(irp, instruction->ptr);
2502 fprintf(irp->f, ",");
2503 ir_print_other_inst_src(irp, instruction->op);
2504 fprintf(irp->f, ",");
2505 ir_print_other_inst_src(irp, instruction->operand);
2506 fprintf(irp->f, ",");
2507 ir_print_other_inst_src(irp, instruction->ordering);
2508 fprintf(irp->f, ")");
2509}
2510
2511static void ir_print_atomic_rmw(IrPrintGen *irp, Stage1AirInstAtomicRmw *instruction) {
2512 fprintf(irp->f, "@atomicRmw(");
2513 ir_print_other_inst_gen(irp, instruction->ptr);
2514 fprintf(irp->f, ",[TODO print op],");
2515 ir_print_other_inst_gen(irp, instruction->operand);
2516 fprintf(irp->f, ",%s)", atomic_order_str(instruction->ordering));
2517}
2518
2519static void ir_print_atomic_load(IrPrintSrc *irp, Stage1ZirInstAtomicLoad *instruction) {
2520 fprintf(irp->f, "@atomicLoad(");
2521 ir_print_other_inst_src(irp, instruction->operand_type);
2522 fprintf(irp->f, ",");
2523 ir_print_other_inst_src(irp, instruction->ptr);
2524 fprintf(irp->f, ",");
2525 ir_print_other_inst_src(irp, instruction->ordering);
2526 fprintf(irp->f, ")");
2527}
2528
2529static void ir_print_atomic_load(IrPrintGen *irp, Stage1AirInstAtomicLoad *instruction) {
2530 fprintf(irp->f, "@atomicLoad(");
2531 ir_print_other_inst_gen(irp, instruction->ptr);
2532 fprintf(irp->f, ",%s)", atomic_order_str(instruction->ordering));
2533}
2534
2535static void ir_print_atomic_store(IrPrintSrc *irp, Stage1ZirInstAtomicStore *instruction) {
2536 fprintf(irp->f, "@atomicStore(");
2537 ir_print_other_inst_src(irp, instruction->operand_type);
2538 fprintf(irp->f, ",");
2539 ir_print_other_inst_src(irp, instruction->ptr);
2540 fprintf(irp->f, ",");
2541 ir_print_other_inst_src(irp, instruction->value);
2542 fprintf(irp->f, ",");
2543 ir_print_other_inst_src(irp, instruction->ordering);
2544 fprintf(irp->f, ")");
2545}
2546
2547static void ir_print_atomic_store(IrPrintGen *irp, Stage1AirInstAtomicStore *instruction) {
2548 fprintf(irp->f, "@atomicStore(");
2549 ir_print_other_inst_gen(irp, instruction->ptr);
2550 fprintf(irp->f, ",");
2551 ir_print_other_inst_gen(irp, instruction->value);
2552 fprintf(irp->f, ",%s)", atomic_order_str(instruction->ordering));
2553}
2554
2555
2556static void ir_print_save_err_ret_addr(IrPrintSrc *irp, Stage1ZirInstSaveErrRetAddr *instruction) {
2557 fprintf(irp->f, "@saveErrRetAddr()");
2558}
2559
2560static void ir_print_save_err_ret_addr(IrPrintGen *irp, Stage1AirInstSaveErrRetAddr *instruction) {
2561 fprintf(irp->f, "@saveErrRetAddr()");
2562}
2563
2564static void ir_print_add_implicit_return_type(IrPrintSrc *irp, Stage1ZirInstAddImplicitReturnType *instruction) {
2565 fprintf(irp->f, "@addImplicitReturnType(");
2566 ir_print_other_inst_src(irp, instruction->value);
2567 fprintf(irp->f, ")");
2568}
2569
2570static void ir_print_float_op(IrPrintSrc *irp, Stage1ZirInstFloatOp *instruction) {
2571 fprintf(irp->f, "@%s(", float_un_op_to_name(instruction->fn_id));
2572 ir_print_other_inst_src(irp, instruction->operand);
2573 fprintf(irp->f, ")");
2574}
2575
2576static void ir_print_float_op(IrPrintGen *irp, Stage1AirInstFloatOp *instruction) {
2577 fprintf(irp->f, "@%s(", float_un_op_to_name(instruction->fn_id));
2578 ir_print_other_inst_gen(irp, instruction->operand);
2579 fprintf(irp->f, ")");
2580}
2581
2582static void ir_print_mul_add(IrPrintSrc *irp, Stage1ZirInstMulAdd *instruction) {
2583 fprintf(irp->f, "@mulAdd(");
2584 ir_print_other_inst_src(irp, instruction->type_value);
2585 fprintf(irp->f, ",");
2586 ir_print_other_inst_src(irp, instruction->op1);
2587 fprintf(irp->f, ",");
2588 ir_print_other_inst_src(irp, instruction->op2);
2589 fprintf(irp->f, ",");
2590 ir_print_other_inst_src(irp, instruction->op3);
2591 fprintf(irp->f, ")");
2592}
2593
2594static void ir_print_mul_add(IrPrintGen *irp, Stage1AirInstMulAdd *instruction) {
2595 fprintf(irp->f, "@mulAdd(");
2596 ir_print_other_inst_gen(irp, instruction->op1);
2597 fprintf(irp->f, ",");
2598 ir_print_other_inst_gen(irp, instruction->op2);
2599 fprintf(irp->f, ",");
2600 ir_print_other_inst_gen(irp, instruction->op3);
2601 fprintf(irp->f, ")");
2602}
2603
2604static void ir_print_decl_var_gen(IrPrintGen *irp, Stage1AirInstDeclVar *decl_var_instruction) {
2605 ZigVar *var = decl_var_instruction->var;
2606 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
2607 const char *name = decl_var_instruction->var->name;
2608 fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name),
2609 var->align_bytes);
2610
2611 ir_print_other_inst_gen(irp, decl_var_instruction->var_ptr);
2612}
2613
2614static void ir_print_has_decl(IrPrintSrc *irp, Stage1ZirInstHasDecl *instruction) {
2615 fprintf(irp->f, "@hasDecl(");
2616 ir_print_other_inst_src(irp, instruction->container);
2617 fprintf(irp->f, ",");
2618 ir_print_other_inst_src(irp, instruction->name);
2619 fprintf(irp->f, ")");
2620}
2621
2622static void ir_print_undeclared_ident(IrPrintSrc *irp, Stage1ZirInstUndeclaredIdent *instruction) {
2623 fprintf(irp->f, "@undeclaredIdent(%s)", buf_ptr(instruction->name));
2624}
2625
2626static void ir_print_union_init_named_field(IrPrintSrc *irp, Stage1ZirInstUnionInitNamedField *instruction) {
2627 fprintf(irp->f, "@unionInit(");
2628 ir_print_other_inst_src(irp, instruction->union_type);
2629 fprintf(irp->f, ", ");
2630 ir_print_other_inst_src(irp, instruction->field_name);
2631 fprintf(irp->f, ", ");
2632 ir_print_other_inst_src(irp, instruction->field_result_loc);
2633 fprintf(irp->f, ", ");
2634 ir_print_other_inst_src(irp, instruction->result_loc);
2635 fprintf(irp->f, ")");
2636}
2637
2638static void ir_print_suspend_begin(IrPrintSrc *irp, Stage1ZirInstSuspendBegin *instruction) {
2639 fprintf(irp->f, "@suspendBegin()");
2640}
2641
2642static void ir_print_suspend_begin(IrPrintGen *irp, Stage1AirInstSuspendBegin *instruction) {
2643 fprintf(irp->f, "@suspendBegin()");
2644}
2645
2646static void ir_print_suspend_finish(IrPrintSrc *irp, Stage1ZirInstSuspendFinish *instruction) {
2647 fprintf(irp->f, "@suspendFinish()");
2648}
2649
2650static void ir_print_suspend_finish(IrPrintGen *irp, Stage1AirInstSuspendFinish *instruction) {
2651 fprintf(irp->f, "@suspendFinish()");
2652}
2653
2654static void ir_print_resume(IrPrintSrc *irp, Stage1ZirInstResume *instruction) {
2655 fprintf(irp->f, "resume ");
2656 ir_print_other_inst_src(irp, instruction->frame);
2657}
2658
2659static void ir_print_resume(IrPrintGen *irp, Stage1AirInstResume *instruction) {
2660 fprintf(irp->f, "resume ");
2661 ir_print_other_inst_gen(irp, instruction->frame);
2662}
2663
2664static void ir_print_await_src(IrPrintSrc *irp, Stage1ZirInstAwait *instruction) {
2665 fprintf(irp->f, "@await(");
2666 ir_print_other_inst_src(irp, instruction->frame);
2667 fprintf(irp->f, ",");
2668 ir_print_result_loc(irp, instruction->result_loc);
2669 fprintf(irp->f, ")");
2670}
2671
2672static void ir_print_await_gen(IrPrintGen *irp, Stage1AirInstAwait *instruction) {
2673 fprintf(irp->f, "@await(");
2674 ir_print_other_inst_gen(irp, instruction->frame);
2675 fprintf(irp->f, ",");
2676 ir_print_other_inst_gen(irp, instruction->result_loc);
2677 fprintf(irp->f, ")");
2678}
2679
2680static void ir_print_spill_begin(IrPrintSrc *irp, Stage1ZirInstSpillBegin *instruction) {
2681 fprintf(irp->f, "@spillBegin(");
2682 ir_print_other_inst_src(irp, instruction->operand);
2683 fprintf(irp->f, ")");
2684}
2685
2686static void ir_print_spill_begin(IrPrintGen *irp, Stage1AirInstSpillBegin *instruction) {
2687 fprintf(irp->f, "@spillBegin(");
2688 ir_print_other_inst_gen(irp, instruction->operand);
2689 fprintf(irp->f, ")");
2690}
2691
2692static void ir_print_spill_end(IrPrintSrc *irp, Stage1ZirInstSpillEnd *instruction) {
2693 fprintf(irp->f, "@spillEnd(");
2694 ir_print_other_inst_src(irp, &instruction->begin->base);
2695 fprintf(irp->f, ")");
2696}
2697
2698static void ir_print_spill_end(IrPrintGen *irp, Stage1AirInstSpillEnd *instruction) {
2699 fprintf(irp->f, "@spillEnd(");
2700 ir_print_other_inst_gen(irp, &instruction->begin->base);
2701 fprintf(irp->f, ")");
2702}
2703
2704static void ir_print_vector_extract_elem(IrPrintGen *irp, Stage1AirInstVectorExtractElem *instruction) {
2705 fprintf(irp->f, "@vectorExtractElem(");
2706 ir_print_other_inst_gen(irp, instruction->vector);
2707 fprintf(irp->f, ",");
2708 ir_print_other_inst_gen(irp, instruction->index);
2709 fprintf(irp->f, ")");
2710}
2711
2712static void ir_print_inst_src(IrPrintSrc *irp, Stage1ZirInst *instruction, bool trailing) {
2713 ir_print_prefix_src(irp, instruction, trailing);
2714 switch (instruction->id) {
2715 case Stage1ZirInstIdInvalid:
2716 zig_unreachable();
2717 case Stage1ZirInstIdReturn:
2718 ir_print_return_src(irp, (Stage1ZirInstReturn *)instruction);
2719 break;
2720 case Stage1ZirInstIdConst:
2721 ir_print_const(irp, (Stage1ZirInstConst *)instruction);
2722 break;
2723 case Stage1ZirInstIdBinOp:
2724 ir_print_bin_op(irp, (Stage1ZirInstBinOp *)instruction);
2725 break;
2726 case Stage1ZirInstIdMergeErrSets:
2727 ir_print_merge_err_sets(irp, (Stage1ZirInstMergeErrSets *)instruction);
2728 break;
2729 case Stage1ZirInstIdDeclVar:
2730 ir_print_decl_var_src(irp, (Stage1ZirInstDeclVar *)instruction);
2731 break;
2732 case Stage1ZirInstIdCallExtra:
2733 ir_print_call_extra(irp, (Stage1ZirInstCallExtra *)instruction);
2734 break;
2735 case Stage1ZirInstIdAsyncCallExtra:
2736 ir_print_async_call_extra(irp, (Stage1ZirInstAsyncCallExtra *)instruction);
2737 break;
2738 case Stage1ZirInstIdCall:
2739 ir_print_call_src(irp, (Stage1ZirInstCall *)instruction);
2740 break;
2741 case Stage1ZirInstIdCallArgs:
2742 ir_print_call_args(irp, (Stage1ZirInstCallArgs *)instruction);
2743 break;
2744 case Stage1ZirInstIdUnOp:
2745 ir_print_un_op(irp, (Stage1ZirInstUnOp *)instruction);
2746 break;
2747 case Stage1ZirInstIdCondBr:
2748 ir_print_cond_br(irp, (Stage1ZirInstCondBr *)instruction);
2749 break;
2750 case Stage1ZirInstIdBr:
2751 ir_print_br(irp, (Stage1ZirInstBr *)instruction);
2752 break;
2753 case Stage1ZirInstIdPhi:
2754 ir_print_phi(irp, (Stage1ZirInstPhi *)instruction);
2755 break;
2756 case Stage1ZirInstIdContainerInitList:
2757 ir_print_container_init_list(irp, (Stage1ZirInstContainerInitList *)instruction);
2758 break;
2759 case Stage1ZirInstIdContainerInitFields:
2760 ir_print_container_init_fields(irp, (Stage1ZirInstContainerInitFields *)instruction);
2761 break;
2762 case Stage1ZirInstIdUnreachable:
2763 ir_print_unreachable(irp, (Stage1ZirInstUnreachable *)instruction);
2764 break;
2765 case Stage1ZirInstIdElemPtr:
2766 ir_print_elem_ptr(irp, (Stage1ZirInstElemPtr *)instruction);
2767 break;
2768 case Stage1ZirInstIdVarPtr:
2769 ir_print_var_ptr(irp, (Stage1ZirInstVarPtr *)instruction);
2770 break;
2771 case Stage1ZirInstIdLoadPtr:
2772 ir_print_load_ptr(irp, (Stage1ZirInstLoadPtr *)instruction);
2773 break;
2774 case Stage1ZirInstIdStorePtr:
2775 ir_print_store_ptr(irp, (Stage1ZirInstStorePtr *)instruction);
2776 break;
2777 case Stage1ZirInstIdTypeOf:
2778 ir_print_typeof(irp, (Stage1ZirInstTypeOf *)instruction);
2779 break;
2780 case Stage1ZirInstIdFieldPtr:
2781 ir_print_field_ptr(irp, (Stage1ZirInstFieldPtr *)instruction);
2782 break;
2783 case Stage1ZirInstIdSetCold:
2784 ir_print_set_cold(irp, (Stage1ZirInstSetCold *)instruction);
2785 break;
2786 case Stage1ZirInstIdSetRuntimeSafety:
2787 ir_print_set_runtime_safety(irp, (Stage1ZirInstSetRuntimeSafety *)instruction);
2788 break;
2789 case Stage1ZirInstIdSetFloatMode:
2790 ir_print_set_float_mode(irp, (Stage1ZirInstSetFloatMode *)instruction);
2791 break;
2792 case Stage1ZirInstIdArrayType:
2793 ir_print_array_type(irp, (Stage1ZirInstArrayType *)instruction);
2794 break;
2795 case Stage1ZirInstIdSliceType:
2796 ir_print_slice_type(irp, (Stage1ZirInstSliceType *)instruction);
2797 break;
2798 case Stage1ZirInstIdAnyFrameType:
2799 ir_print_any_frame_type(irp, (Stage1ZirInstAnyFrameType *)instruction);
2800 break;
2801 case Stage1ZirInstIdAsm:
2802 ir_print_asm_src(irp, (Stage1ZirInstAsm *)instruction);
2803 break;
2804 case Stage1ZirInstIdSizeOf:
2805 ir_print_size_of(irp, (Stage1ZirInstSizeOf *)instruction);
2806 break;
2807 case Stage1ZirInstIdTestNonNull:
2808 ir_print_test_non_null(irp, (Stage1ZirInstTestNonNull *)instruction);
2809 break;
2810 case Stage1ZirInstIdOptionalUnwrapPtr:
2811 ir_print_optional_unwrap_ptr(irp, (Stage1ZirInstOptionalUnwrapPtr *)instruction);
2812 break;
2813 case Stage1ZirInstIdPopCount:
2814 ir_print_pop_count(irp, (Stage1ZirInstPopCount *)instruction);
2815 break;
2816 case Stage1ZirInstIdCtz:
2817 ir_print_ctz(irp, (Stage1ZirInstCtz *)instruction);
2818 break;
2819 case Stage1ZirInstIdBswap:
2820 ir_print_bswap(irp, (Stage1ZirInstBswap *)instruction);
2821 break;
2822 case Stage1ZirInstIdBitReverse:
2823 ir_print_bit_reverse(irp, (Stage1ZirInstBitReverse *)instruction);
2824 break;
2825 case Stage1ZirInstIdSwitchBr:
2826 ir_print_switch_br(irp, (Stage1ZirInstSwitchBr *)instruction);
2827 break;
2828 case Stage1ZirInstIdSwitchVar:
2829 ir_print_switch_var(irp, (Stage1ZirInstSwitchVar *)instruction);
2830 break;
2831 case Stage1ZirInstIdSwitchElseVar:
2832 ir_print_switch_else_var(irp, (Stage1ZirInstSwitchElseVar *)instruction);
2833 break;
2834 case Stage1ZirInstIdSwitchTarget:
2835 ir_print_switch_target(irp, (Stage1ZirInstSwitchTarget *)instruction);
2836 break;
2837 case Stage1ZirInstIdImport:
2838 ir_print_import(irp, (Stage1ZirInstImport *)instruction);
2839 break;
2840 case Stage1ZirInstIdRef:
2841 ir_print_ref(irp, (Stage1ZirInstRef *)instruction);
2842 break;
2843 case Stage1ZirInstIdCompileErr:
2844 ir_print_compile_err(irp, (Stage1ZirInstCompileErr *)instruction);
2845 break;
2846 case Stage1ZirInstIdCompileLog:
2847 ir_print_compile_log(irp, (Stage1ZirInstCompileLog *)instruction);
2848 break;
2849 case Stage1ZirInstIdErrName:
2850 ir_print_err_name(irp, (Stage1ZirInstErrName *)instruction);
2851 break;
2852 case Stage1ZirInstIdCImport:
2853 ir_print_c_import(irp, (Stage1ZirInstCImport *)instruction);
2854 break;
2855 case Stage1ZirInstIdCInclude:
2856 ir_print_c_include(irp, (Stage1ZirInstCInclude *)instruction);
2857 break;
2858 case Stage1ZirInstIdCDefine:
2859 ir_print_c_define(irp, (Stage1ZirInstCDefine *)instruction);
2860 break;
2861 case Stage1ZirInstIdCUndef:
2862 ir_print_c_undef(irp, (Stage1ZirInstCUndef *)instruction);
2863 break;
2864 case Stage1ZirInstIdEmbedFile:
2865 ir_print_embed_file(irp, (Stage1ZirInstEmbedFile *)instruction);
2866 break;
2867 case Stage1ZirInstIdCmpxchg:
2868 ir_print_cmpxchg_src(irp, (Stage1ZirInstCmpxchg *)instruction);
2869 break;
2870 case Stage1ZirInstIdFence:
2871 ir_print_fence(irp, (Stage1ZirInstFence *)instruction);
2872 break;
2873 case Stage1ZirInstIdReduce:
2874 ir_print_reduce(irp, (Stage1ZirInstReduce *)instruction);
2875 break;
2876 case Stage1ZirInstIdTruncate:
2877 ir_print_truncate(irp, (Stage1ZirInstTruncate *)instruction);
2878 break;
2879 case Stage1ZirInstIdIntCast:
2880 ir_print_int_cast(irp, (Stage1ZirInstIntCast *)instruction);
2881 break;
2882 case Stage1ZirInstIdFloatCast:
2883 ir_print_float_cast(irp, (Stage1ZirInstFloatCast *)instruction);
2884 break;
2885 case Stage1ZirInstIdErrSetCast:
2886 ir_print_err_set_cast(irp, (Stage1ZirInstErrSetCast *)instruction);
2887 break;
2888 case Stage1ZirInstIdIntToFloat:
2889 ir_print_int_to_float(irp, (Stage1ZirInstIntToFloat *)instruction);
2890 break;
2891 case Stage1ZirInstIdFloatToInt:
2892 ir_print_float_to_int(irp, (Stage1ZirInstFloatToInt *)instruction);
2893 break;
2894 case Stage1ZirInstIdBoolToInt:
2895 ir_print_bool_to_int(irp, (Stage1ZirInstBoolToInt *)instruction);
2896 break;
2897 case Stage1ZirInstIdVectorType:
2898 ir_print_vector_type(irp, (Stage1ZirInstVectorType *)instruction);
2899 break;
2900 case Stage1ZirInstIdShuffleVector:
2901 ir_print_shuffle_vector(irp, (Stage1ZirInstShuffleVector *)instruction);
2902 break;
2903 case Stage1ZirInstIdSelect:
2904 ir_print_select(irp, (Stage1ZirInstSelect *)instruction);
2905 break;
2906 case Stage1ZirInstIdSplat:
2907 ir_print_splat_src(irp, (Stage1ZirInstSplat *)instruction);
2908 break;
2909 case Stage1ZirInstIdBoolNot:
2910 ir_print_bool_not(irp, (Stage1ZirInstBoolNot *)instruction);
2911 break;
2912 case Stage1ZirInstIdMemset:
2913 ir_print_memset(irp, (Stage1ZirInstMemset *)instruction);
2914 break;
2915 case Stage1ZirInstIdMemcpy:
2916 ir_print_memcpy(irp, (Stage1ZirInstMemcpy *)instruction);
2917 break;
2918 case Stage1ZirInstIdSlice:
2919 ir_print_slice_src(irp, (Stage1ZirInstSlice *)instruction);
2920 break;
2921 case Stage1ZirInstIdBreakpoint:
2922 ir_print_breakpoint(irp, (Stage1ZirInstBreakpoint *)instruction);
2923 break;
2924 case Stage1ZirInstIdReturnAddress:
2925 ir_print_return_address(irp, (Stage1ZirInstReturnAddress *)instruction);
2926 break;
2927 case Stage1ZirInstIdFrameAddress:
2928 ir_print_frame_address(irp, (Stage1ZirInstFrameAddress *)instruction);
2929 break;
2930 case Stage1ZirInstIdFrameHandle:
2931 ir_print_handle(irp, (Stage1ZirInstFrameHandle *)instruction);
2932 break;
2933 case Stage1ZirInstIdFrameType:
2934 ir_print_frame_type(irp, (Stage1ZirInstFrameType *)instruction);
2935 break;
2936 case Stage1ZirInstIdFrameSize:
2937 ir_print_frame_size_src(irp, (Stage1ZirInstFrameSize *)instruction);
2938 break;
2939 case Stage1ZirInstIdAlignOf:
2940 ir_print_align_of(irp, (Stage1ZirInstAlignOf *)instruction);
2941 break;
2942 case Stage1ZirInstIdOverflowOp:
2943 ir_print_overflow_op(irp, (Stage1ZirInstOverflowOp *)instruction);
2944 break;
2945 case Stage1ZirInstIdTestErr:
2946 ir_print_test_err_src(irp, (Stage1ZirInstTestErr *)instruction);
2947 break;
2948 case Stage1ZirInstIdUnwrapErrCode:
2949 ir_print_unwrap_err_code(irp, (Stage1ZirInstUnwrapErrCode *)instruction);
2950 break;
2951 case Stage1ZirInstIdUnwrapErrPayload:
2952 ir_print_unwrap_err_payload(irp, (Stage1ZirInstUnwrapErrPayload *)instruction);
2953 break;
2954 case Stage1ZirInstIdFnProto:
2955 ir_print_fn_proto(irp, (Stage1ZirInstFnProto *)instruction);
2956 break;
2957 case Stage1ZirInstIdTestComptime:
2958 ir_print_test_comptime(irp, (Stage1ZirInstTestComptime *)instruction);
2959 break;
2960 case Stage1ZirInstIdPtrCast:
2961 ir_print_ptr_cast_src(irp, (Stage1ZirInstPtrCast *)instruction);
2962 break;
2963 case Stage1ZirInstIdBitCast:
2964 ir_print_bit_cast_src(irp, (Stage1ZirInstBitCast *)instruction);
2965 break;
2966 case Stage1ZirInstIdPtrToInt:
2967 ir_print_ptr_to_int(irp, (Stage1ZirInstPtrToInt *)instruction);
2968 break;
2969 case Stage1ZirInstIdIntToPtr:
2970 ir_print_int_to_ptr(irp, (Stage1ZirInstIntToPtr *)instruction);
2971 break;
2972 case Stage1ZirInstIdIntToEnum:
2973 ir_print_int_to_enum(irp, (Stage1ZirInstIntToEnum *)instruction);
2974 break;
2975 case Stage1ZirInstIdIntToErr:
2976 ir_print_int_to_err(irp, (Stage1ZirInstIntToErr *)instruction);
2977 break;
2978 case Stage1ZirInstIdErrToInt:
2979 ir_print_err_to_int(irp, (Stage1ZirInstErrToInt *)instruction);
2980 break;
2981 case Stage1ZirInstIdCheckSwitchProngsUnderNo:
2982 ir_print_check_switch_prongs(irp, (Stage1ZirInstCheckSwitchProngs *)instruction, false);
2983 break;
2984 case Stage1ZirInstIdCheckSwitchProngsUnderYes:
2985 ir_print_check_switch_prongs(irp, (Stage1ZirInstCheckSwitchProngs *)instruction, true);
2986 break;
2987 case Stage1ZirInstIdCheckStatementIsVoid:
2988 ir_print_check_statement_is_void(irp, (Stage1ZirInstCheckStatementIsVoid *)instruction);
2989 break;
2990 case Stage1ZirInstIdTypeName:
2991 ir_print_type_name(irp, (Stage1ZirInstTypeName *)instruction);
2992 break;
2993 case Stage1ZirInstIdTagName:
2994 ir_print_tag_name(irp, (Stage1ZirInstTagName *)instruction);
2995 break;
2996 case Stage1ZirInstIdPtrType:
2997 ir_print_ptr_type(irp, (Stage1ZirInstPtrType *)instruction);
2998 break;
2999 case Stage1ZirInstIdPtrTypeSimple:
3000 ir_print_ptr_type_simple(irp, (Stage1ZirInstPtrTypeSimple *)instruction, false);
3001 break;
3002 case Stage1ZirInstIdPtrTypeSimpleConst:
3003 ir_print_ptr_type_simple(irp, (Stage1ZirInstPtrTypeSimple *)instruction, true);
3004 break;
3005 case Stage1ZirInstIdDeclRef:
3006 ir_print_decl_ref(irp, (Stage1ZirInstDeclRef *)instruction);
3007 break;
3008 case Stage1ZirInstIdPanic:
3009 ir_print_panic(irp, (Stage1ZirInstPanic *)instruction);
3010 break;
3011 case Stage1ZirInstIdFieldParentPtr:
3012 ir_print_field_parent_ptr(irp, (Stage1ZirInstFieldParentPtr *)instruction);
3013 break;
3014 case Stage1ZirInstIdOffsetOf:
3015 ir_print_offset_of(irp, (Stage1ZirInstOffsetOf *)instruction);
3016 break;
3017 case Stage1ZirInstIdBitOffsetOf:
3018 ir_print_bit_offset_of(irp, (Stage1ZirInstBitOffsetOf *)instruction);
3019 break;
3020 case Stage1ZirInstIdTypeInfo:
3021 ir_print_type_info(irp, (Stage1ZirInstTypeInfo *)instruction);
3022 break;
3023 case Stage1ZirInstIdType:
3024 ir_print_type(irp, (Stage1ZirInstType *)instruction);
3025 break;
3026 case Stage1ZirInstIdHasField:
3027 ir_print_has_field(irp, (Stage1ZirInstHasField *)instruction);
3028 break;
3029 case Stage1ZirInstIdSetEvalBranchQuota:
3030 ir_print_set_eval_branch_quota(irp, (Stage1ZirInstSetEvalBranchQuota *)instruction);
3031 break;
3032 case Stage1ZirInstIdAlignCast:
3033 ir_print_align_cast(irp, (Stage1ZirInstAlignCast *)instruction);
3034 break;
3035 case Stage1ZirInstIdImplicitCast:
3036 ir_print_implicit_cast(irp, (Stage1ZirInstImplicitCast *)instruction);
3037 break;
3038 case Stage1ZirInstIdResolveResult:
3039 ir_print_resolve_result(irp, (Stage1ZirInstResolveResult *)instruction);
3040 break;
3041 case Stage1ZirInstIdResetResult:
3042 ir_print_reset_result(irp, (Stage1ZirInstResetResult *)instruction);
3043 break;
3044 case Stage1ZirInstIdSetAlignStack:
3045 ir_print_set_align_stack(irp, (Stage1ZirInstSetAlignStack *)instruction);
3046 break;
3047 case Stage1ZirInstIdArgTypeAllowVarFalse:
3048 ir_print_arg_type(irp, (Stage1ZirInstArgType *)instruction, false);
3049 break;
3050 case Stage1ZirInstIdArgTypeAllowVarTrue:
3051 ir_print_arg_type(irp, (Stage1ZirInstArgType *)instruction, true);
3052 break;
3053 case Stage1ZirInstIdExport:
3054 ir_print_export(irp, (Stage1ZirInstExport *)instruction);
3055 break;
3056 case Stage1ZirInstIdExtern:
3057 ir_print_extern(irp, (Stage1ZirInstExtern*)instruction);
3058 break;
3059 case Stage1ZirInstIdErrorReturnTrace:
3060 ir_print_error_return_trace(irp, (Stage1ZirInstErrorReturnTrace *)instruction);
3061 break;
3062 case Stage1ZirInstIdErrorUnion:
3063 ir_print_error_union(irp, (Stage1ZirInstErrorUnion *)instruction);
3064 break;
3065 case Stage1ZirInstIdAtomicRmw:
3066 ir_print_atomic_rmw(irp, (Stage1ZirInstAtomicRmw *)instruction);
3067 break;
3068 case Stage1ZirInstIdSaveErrRetAddr:
3069 ir_print_save_err_ret_addr(irp, (Stage1ZirInstSaveErrRetAddr *)instruction);
3070 break;
3071 case Stage1ZirInstIdAddImplicitReturnType:
3072 ir_print_add_implicit_return_type(irp, (Stage1ZirInstAddImplicitReturnType *)instruction);
3073 break;
3074 case Stage1ZirInstIdFloatOp:
3075 ir_print_float_op(irp, (Stage1ZirInstFloatOp *)instruction);
3076 break;
3077 case Stage1ZirInstIdMulAdd:
3078 ir_print_mul_add(irp, (Stage1ZirInstMulAdd *)instruction);
3079 break;
3080 case Stage1ZirInstIdAtomicLoad:
3081 ir_print_atomic_load(irp, (Stage1ZirInstAtomicLoad *)instruction);
3082 break;
3083 case Stage1ZirInstIdAtomicStore:
3084 ir_print_atomic_store(irp, (Stage1ZirInstAtomicStore *)instruction);
3085 break;
3086 case Stage1ZirInstIdEnumToInt:
3087 ir_print_enum_to_int(irp, (Stage1ZirInstEnumToInt *)instruction);
3088 break;
3089 case Stage1ZirInstIdCheckRuntimeScope:
3090 ir_print_check_runtime_scope(irp, (Stage1ZirInstCheckRuntimeScope *)instruction);
3091 break;
3092 case Stage1ZirInstIdHasDecl:
3093 ir_print_has_decl(irp, (Stage1ZirInstHasDecl *)instruction);
3094 break;
3095 case Stage1ZirInstIdUndeclaredIdent:
3096 ir_print_undeclared_ident(irp, (Stage1ZirInstUndeclaredIdent *)instruction);
3097 break;
3098 case Stage1ZirInstIdAlloca:
3099 ir_print_alloca_src(irp, (Stage1ZirInstAlloca *)instruction);
3100 break;
3101 case Stage1ZirInstIdEndExpr:
3102 ir_print_end_expr(irp, (Stage1ZirInstEndExpr *)instruction);
3103 break;
3104 case Stage1ZirInstIdUnionInitNamedField:
3105 ir_print_union_init_named_field(irp, (Stage1ZirInstUnionInitNamedField *)instruction);
3106 break;
3107 case Stage1ZirInstIdSuspendBegin:
3108 ir_print_suspend_begin(irp, (Stage1ZirInstSuspendBegin *)instruction);
3109 break;
3110 case Stage1ZirInstIdSuspendFinish:
3111 ir_print_suspend_finish(irp, (Stage1ZirInstSuspendFinish *)instruction);
3112 break;
3113 case Stage1ZirInstIdResume:
3114 ir_print_resume(irp, (Stage1ZirInstResume *)instruction);
3115 break;
3116 case Stage1ZirInstIdAwait:
3117 ir_print_await_src(irp, (Stage1ZirInstAwait *)instruction);
3118 break;
3119 case Stage1ZirInstIdSpillBegin:
3120 ir_print_spill_begin(irp, (Stage1ZirInstSpillBegin *)instruction);
3121 break;
3122 case Stage1ZirInstIdSpillEnd:
3123 ir_print_spill_end(irp, (Stage1ZirInstSpillEnd *)instruction);
3124 break;
3125 case Stage1ZirInstIdClz:
3126 ir_print_clz(irp, (Stage1ZirInstClz *)instruction);
3127 break;
3128 case Stage1ZirInstIdWasmMemorySize:
3129 ir_print_wasm_memory_size(irp, (Stage1ZirInstWasmMemorySize *)instruction);
3130 break;
3131 case Stage1ZirInstIdWasmMemoryGrow:
3132 ir_print_wasm_memory_grow(irp, (Stage1ZirInstWasmMemoryGrow *)instruction);
3133 break;
3134 case Stage1ZirInstIdSrc:
3135 ir_print_builtin_src(irp, (Stage1ZirInstSrc *)instruction);
3136 break;
3137 case Stage1ZirInstIdPrefetch:
3138 ir_print_prefetch(irp, (Stage1ZirInstPrefetch *)instruction);
3139 break;
3140 case Stage1ZirInstIdAddrSpaceCast:
3141 ir_print_addrspace_cast(irp, (Stage1ZirInstAddrSpaceCast *)instruction);
3142 break;
3143 }
3144 fprintf(irp->f, "\n");
3145}
3146
3147static void ir_print_inst_gen(IrPrintGen *irp, Stage1AirInst *instruction, bool trailing) {
3148 ir_print_prefix_gen(irp, instruction, trailing);
3149 switch (instruction->id) {
3150 case Stage1AirInstIdInvalid:
3151 zig_unreachable();
3152 case Stage1AirInstIdReturn:
3153 ir_print_return_gen(irp, (Stage1AirInstReturn *)instruction);
3154 break;
3155 case Stage1AirInstIdConst:
3156 ir_print_const(irp, (Stage1AirInstConst *)instruction);
3157 break;
3158 case Stage1AirInstIdBinOp:
3159 ir_print_bin_op(irp, (Stage1AirInstBinOp *)instruction);
3160 break;
3161 case Stage1AirInstIdDeclVar:
3162 ir_print_decl_var_gen(irp, (Stage1AirInstDeclVar *)instruction);
3163 break;
3164 case Stage1AirInstIdCast:
3165 ir_print_cast(irp, (Stage1AirInstCast *)instruction);
3166 break;
3167 case Stage1AirInstIdCall:
3168 ir_print_call_gen(irp, (Stage1AirInstCall *)instruction);
3169 break;
3170 case Stage1AirInstIdCondBr:
3171 ir_print_cond_br(irp, (Stage1AirInstCondBr *)instruction);
3172 break;
3173 case Stage1AirInstIdBr:
3174 ir_print_br(irp, (Stage1AirInstBr *)instruction);
3175 break;
3176 case Stage1AirInstIdPhi:
3177 ir_print_phi(irp, (Stage1AirInstPhi *)instruction);
3178 break;
3179 case Stage1AirInstIdUnreachable:
3180 ir_print_unreachable(irp, (Stage1AirInstUnreachable *)instruction);
3181 break;
3182 case Stage1AirInstIdElemPtr:
3183 ir_print_elem_ptr(irp, (Stage1AirInstElemPtr *)instruction);
3184 break;
3185 case Stage1AirInstIdVarPtr:
3186 ir_print_var_ptr(irp, (Stage1AirInstVarPtr *)instruction);
3187 break;
3188 case Stage1AirInstIdReturnPtr:
3189 ir_print_return_ptr(irp, (Stage1AirInstReturnPtr *)instruction);
3190 break;
3191 case Stage1AirInstIdLoadPtr:
3192 ir_print_load_ptr_gen(irp, (Stage1AirInstLoadPtr *)instruction);
3193 break;
3194 case Stage1AirInstIdStorePtr:
3195 ir_print_store_ptr(irp, (Stage1AirInstStorePtr *)instruction);
3196 break;
3197 case Stage1AirInstIdStructFieldPtr:
3198 ir_print_struct_field_ptr(irp, (Stage1AirInstStructFieldPtr *)instruction);
3199 break;
3200 case Stage1AirInstIdUnionFieldPtr:
3201 ir_print_union_field_ptr(irp, (Stage1AirInstUnionFieldPtr *)instruction);
3202 break;
3203 case Stage1AirInstIdAsm:
3204 ir_print_asm_gen(irp, (Stage1AirInstAsm *)instruction);
3205 break;
3206 case Stage1AirInstIdTestNonNull:
3207 ir_print_test_non_null(irp, (Stage1AirInstTestNonNull *)instruction);
3208 break;
3209 case Stage1AirInstIdOptionalUnwrapPtr:
3210 ir_print_optional_unwrap_ptr(irp, (Stage1AirInstOptionalUnwrapPtr *)instruction);
3211 break;
3212 case Stage1AirInstIdPopCount:
3213 ir_print_pop_count(irp, (Stage1AirInstPopCount *)instruction);
3214 break;
3215 case Stage1AirInstIdClz:
3216 ir_print_clz(irp, (Stage1AirInstClz *)instruction);
3217 break;
3218 case Stage1AirInstIdCtz:
3219 ir_print_ctz(irp, (Stage1AirInstCtz *)instruction);
3220 break;
3221 case Stage1AirInstIdBswap:
3222 ir_print_bswap(irp, (Stage1AirInstBswap *)instruction);
3223 break;
3224 case Stage1AirInstIdBitReverse:
3225 ir_print_bit_reverse(irp, (Stage1AirInstBitReverse *)instruction);
3226 break;
3227 case Stage1AirInstIdSwitchBr:
3228 ir_print_switch_br(irp, (Stage1AirInstSwitchBr *)instruction);
3229 break;
3230 case Stage1AirInstIdUnionTag:
3231 ir_print_union_tag(irp, (Stage1AirInstUnionTag *)instruction);
3232 break;
3233 case Stage1AirInstIdRef:
3234 ir_print_ref_gen(irp, (Stage1AirInstRef *)instruction);
3235 break;
3236 case Stage1AirInstIdErrName:
3237 ir_print_err_name(irp, (Stage1AirInstErrName *)instruction);
3238 break;
3239 case Stage1AirInstIdCmpxchg:
3240 ir_print_cmpxchg_gen(irp, (Stage1AirInstCmpxchg *)instruction);
3241 break;
3242 case Stage1AirInstIdFence:
3243 ir_print_fence(irp, (Stage1AirInstFence *)instruction);
3244 break;
3245 case Stage1AirInstIdReduce:
3246 ir_print_reduce(irp, (Stage1AirInstReduce *)instruction);
3247 break;
3248 case Stage1AirInstIdTruncate:
3249 ir_print_truncate(irp, (Stage1AirInstTruncate *)instruction);
3250 break;
3251 case Stage1AirInstIdShuffleVector:
3252 ir_print_shuffle_vector(irp, (Stage1AirInstShuffleVector *)instruction);
3253 break;
3254 case Stage1AirInstIdSelect:
3255 ir_print_select(irp, (Stage1AirInstSelect *)instruction);
3256 break;
3257 case Stage1AirInstIdSplat:
3258 ir_print_splat_gen(irp, (Stage1AirInstSplat *)instruction);
3259 break;
3260 case Stage1AirInstIdBoolNot:
3261 ir_print_bool_not(irp, (Stage1AirInstBoolNot *)instruction);
3262 break;
3263 case Stage1AirInstIdMemset:
3264 ir_print_memset(irp, (Stage1AirInstMemset *)instruction);
3265 break;
3266 case Stage1AirInstIdMemcpy:
3267 ir_print_memcpy(irp, (Stage1AirInstMemcpy *)instruction);
3268 break;
3269 case Stage1AirInstIdSlice:
3270 ir_print_slice_gen(irp, (Stage1AirInstSlice *)instruction);
3271 break;
3272 case Stage1AirInstIdBreakpoint:
3273 ir_print_breakpoint(irp, (Stage1AirInstBreakpoint *)instruction);
3274 break;
3275 case Stage1AirInstIdReturnAddress:
3276 ir_print_return_address(irp, (Stage1AirInstReturnAddress *)instruction);
3277 break;
3278 case Stage1AirInstIdFrameAddress:
3279 ir_print_frame_address(irp, (Stage1AirInstFrameAddress *)instruction);
3280 break;
3281 case Stage1AirInstIdFrameHandle:
3282 ir_print_handle(irp, (Stage1AirInstFrameHandle *)instruction);
3283 break;
3284 case Stage1AirInstIdFrameSize:
3285 ir_print_frame_size_gen(irp, (Stage1AirInstFrameSize *)instruction);
3286 break;
3287 case Stage1AirInstIdOverflowOp:
3288 ir_print_overflow_op(irp, (Stage1AirInstOverflowOp *)instruction);
3289 break;
3290 case Stage1AirInstIdTestErr:
3291 ir_print_test_err_gen(irp, (Stage1AirInstTestErr *)instruction);
3292 break;
3293 case Stage1AirInstIdUnwrapErrCode:
3294 ir_print_unwrap_err_code(irp, (Stage1AirInstUnwrapErrCode *)instruction);
3295 break;
3296 case Stage1AirInstIdUnwrapErrPayload:
3297 ir_print_unwrap_err_payload(irp, (Stage1AirInstUnwrapErrPayload *)instruction);
3298 break;
3299 case Stage1AirInstIdOptionalWrap:
3300 ir_print_optional_wrap(irp, (Stage1AirInstOptionalWrap *)instruction);
3301 break;
3302 case Stage1AirInstIdErrWrapCode:
3303 ir_print_err_wrap_code(irp, (Stage1AirInstErrWrapCode *)instruction);
3304 break;
3305 case Stage1AirInstIdErrWrapPayload:
3306 ir_print_err_wrap_payload(irp, (Stage1AirInstErrWrapPayload *)instruction);
3307 break;
3308 case Stage1AirInstIdPtrCast:
3309 ir_print_ptr_cast_gen(irp, (Stage1AirInstPtrCast *)instruction);
3310 break;
3311 case Stage1AirInstIdBitCast:
3312 ir_print_bit_cast_gen(irp, (Stage1AirInstBitCast *)instruction);
3313 break;
3314 case Stage1AirInstIdWidenOrShorten:
3315 ir_print_widen_or_shorten(irp, (Stage1AirInstWidenOrShorten *)instruction);
3316 break;
3317 case Stage1AirInstIdPtrToInt:
3318 ir_print_ptr_to_int(irp, (Stage1AirInstPtrToInt *)instruction);
3319 break;
3320 case Stage1AirInstIdIntToPtr:
3321 ir_print_int_to_ptr(irp, (Stage1AirInstIntToPtr *)instruction);
3322 break;
3323 case Stage1AirInstIdIntToEnum:
3324 ir_print_int_to_enum(irp, (Stage1AirInstIntToEnum *)instruction);
3325 break;
3326 case Stage1AirInstIdIntToErr:
3327 ir_print_int_to_err(irp, (Stage1AirInstIntToErr *)instruction);
3328 break;
3329 case Stage1AirInstIdErrToInt:
3330 ir_print_err_to_int(irp, (Stage1AirInstErrToInt *)instruction);
3331 break;
3332 case Stage1AirInstIdTagName:
3333 ir_print_tag_name(irp, (Stage1AirInstTagName *)instruction);
3334 break;
3335 case Stage1AirInstIdPanic:
3336 ir_print_panic(irp, (Stage1AirInstPanic *)instruction);
3337 break;
3338 case Stage1AirInstIdFieldParentPtr:
3339 ir_print_field_parent_ptr(irp, (Stage1AirInstFieldParentPtr *)instruction);
3340 break;
3341 case Stage1AirInstIdAlignCast:
3342 ir_print_align_cast(irp, (Stage1AirInstAlignCast *)instruction);
3343 break;
3344 case Stage1AirInstIdErrorReturnTrace:
3345 ir_print_error_return_trace(irp, (Stage1AirInstErrorReturnTrace *)instruction);
3346 break;
3347 case Stage1AirInstIdAtomicRmw:
3348 ir_print_atomic_rmw(irp, (Stage1AirInstAtomicRmw *)instruction);
3349 break;
3350 case Stage1AirInstIdSaveErrRetAddr:
3351 ir_print_save_err_ret_addr(irp, (Stage1AirInstSaveErrRetAddr *)instruction);
3352 break;
3353 case Stage1AirInstIdFloatOp:
3354 ir_print_float_op(irp, (Stage1AirInstFloatOp *)instruction);
3355 break;
3356 case Stage1AirInstIdMulAdd:
3357 ir_print_mul_add(irp, (Stage1AirInstMulAdd *)instruction);
3358 break;
3359 case Stage1AirInstIdAtomicLoad:
3360 ir_print_atomic_load(irp, (Stage1AirInstAtomicLoad *)instruction);
3361 break;
3362 case Stage1AirInstIdAtomicStore:
3363 ir_print_atomic_store(irp, (Stage1AirInstAtomicStore *)instruction);
3364 break;
3365 case Stage1AirInstIdArrayToVector:
3366 ir_print_array_to_vector(irp, (Stage1AirInstArrayToVector *)instruction);
3367 break;
3368 case Stage1AirInstIdVectorToArray:
3369 ir_print_vector_to_array(irp, (Stage1AirInstVectorToArray *)instruction);
3370 break;
3371 case Stage1AirInstIdPtrOfArrayToSlice:
3372 ir_print_ptr_of_array_to_slice(irp, (Stage1AirInstPtrOfArrayToSlice *)instruction);
3373 break;
3374 case Stage1AirInstIdAssertZero:
3375 ir_print_assert_zero(irp, (Stage1AirInstAssertZero *)instruction);
3376 break;
3377 case Stage1AirInstIdAssertNonNull:
3378 ir_print_assert_non_null(irp, (Stage1AirInstAssertNonNull *)instruction);
3379 break;
3380 case Stage1AirInstIdAlloca:
3381 ir_print_alloca_gen(irp, (Stage1AirInstAlloca *)instruction);
3382 break;
3383 case Stage1AirInstIdSuspendBegin:
3384 ir_print_suspend_begin(irp, (Stage1AirInstSuspendBegin *)instruction);
3385 break;
3386 case Stage1AirInstIdSuspendFinish:
3387 ir_print_suspend_finish(irp, (Stage1AirInstSuspendFinish *)instruction);
3388 break;
3389 case Stage1AirInstIdResume:
3390 ir_print_resume(irp, (Stage1AirInstResume *)instruction);
3391 break;
3392 case Stage1AirInstIdAwait:
3393 ir_print_await_gen(irp, (Stage1AirInstAwait *)instruction);
3394 break;
3395 case Stage1AirInstIdSpillBegin:
3396 ir_print_spill_begin(irp, (Stage1AirInstSpillBegin *)instruction);
3397 break;
3398 case Stage1AirInstIdSpillEnd:
3399 ir_print_spill_end(irp, (Stage1AirInstSpillEnd *)instruction);
3400 break;
3401 case Stage1AirInstIdVectorExtractElem:
3402 ir_print_vector_extract_elem(irp, (Stage1AirInstVectorExtractElem *)instruction);
3403 break;
3404 case Stage1AirInstIdVectorStoreElem:
3405 ir_print_vector_store_elem(irp, (Stage1AirInstVectorStoreElem *)instruction);
3406 break;
3407 case Stage1AirInstIdBinaryNot:
3408 ir_print_binary_not(irp, (Stage1AirInstBinaryNot *)instruction);
3409 break;
3410 case Stage1AirInstIdNegation:
3411 ir_print_negation(irp, (Stage1AirInstNegation *)instruction);
3412 break;
3413 case Stage1AirInstIdWasmMemorySize:
3414 ir_print_wasm_memory_size(irp, (Stage1AirInstWasmMemorySize *)instruction);
3415 break;
3416 case Stage1AirInstIdWasmMemoryGrow:
3417 ir_print_wasm_memory_grow(irp, (Stage1AirInstWasmMemoryGrow *)instruction);
3418 break;
3419 case Stage1AirInstIdExtern:
3420 ir_print_extern(irp, (Stage1AirInstExtern *)instruction);
3421 break;
3422 case Stage1AirInstIdPrefetch:
3423 ir_print_prefetch(irp, (Stage1AirInstPrefetch *)instruction);
3424 break;
3425
3426 }
3427 fprintf(irp->f, "\n");
3428}
3429
3430static void irp_print_basic_block_src(IrPrintSrc *irp, Stage1ZirBasicBlock *current_block) {
3431 fprintf(irp->f, "%s_%" PRIu32 ":\n", current_block->name_hint, current_block->debug_id);
3432 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
3433 Stage1ZirInst *instruction = current_block->instruction_list.at(instr_i);
3434 ir_print_inst_src(irp, instruction, false);
3435 }
3436}
3437
3438static void irp_print_basic_block_gen(IrPrintGen *irp, Stage1AirBasicBlock *current_block) {
3439 fprintf(irp->f, "%s_%" PRIu32 ":\n", current_block->name_hint, current_block->debug_id);
3440 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
3441 Stage1AirInst *instruction = current_block->instruction_list.at(instr_i);
3442 irp->printed.put(instruction, 0);
3443 irp->pending.clear();
3444 ir_print_inst_gen(irp, instruction, false);
3445 for (size_t j = 0; j < irp->pending.length; ++j)
3446 ir_print_inst_gen(irp, irp->pending.at(j), true);
3447 }
3448}
3449
3450void ir_print_basic_block_src(CodeGen *codegen, FILE *f, Stage1ZirBasicBlock *bb, int indent_size) {
3451 IrPrintSrc ir_print = {};
3452 ir_print.codegen = codegen;
3453 ir_print.f = f;
3454 ir_print.indent = indent_size;
3455 ir_print.indent_size = indent_size;
3456
3457 irp_print_basic_block_src(&ir_print, bb);
3458}
3459
3460void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, Stage1AirBasicBlock *bb, int indent_size) {
3461 IrPrintGen ir_print = {};
3462 ir_print.codegen = codegen;
3463 ir_print.f = f;
3464 ir_print.indent = indent_size;
3465 ir_print.indent_size = indent_size;
3466 ir_print.printed = {};
3467 ir_print.printed.init(64);
3468 ir_print.pending = {};
3469
3470 irp_print_basic_block_gen(&ir_print, bb);
3471
3472 ir_print.pending.deinit();
3473 ir_print.printed.deinit();
3474}
3475
3476void ir_print_src(CodeGen *codegen, FILE *f, Stage1Zir *executable, int indent_size) {
3477 IrPrintSrc ir_print = {};
3478 IrPrintSrc *irp = &ir_print;
3479 irp->codegen = codegen;
3480 irp->f = f;
3481 irp->indent = indent_size;
3482 irp->indent_size = indent_size;
3483
3484 for (size_t bb_i = 0; bb_i < executable->basic_block_list.length; bb_i += 1) {
3485 irp_print_basic_block_src(irp, executable->basic_block_list.at(bb_i));
3486 }
3487}
3488
3489void ir_print_gen(CodeGen *codegen, FILE *f, Stage1Air *executable, int indent_size) {
3490 IrPrintGen ir_print = {};
3491 IrPrintGen *irp = &ir_print;
3492 irp->codegen = codegen;
3493 irp->f = f;
3494 irp->indent = indent_size;
3495 irp->indent_size = indent_size;
3496 irp->printed = {};
3497 irp->printed.init(64);
3498 irp->pending = {};
3499
3500 for (size_t bb_i = 0; bb_i < executable->basic_block_list.length; bb_i += 1) {
3501 irp_print_basic_block_gen(irp, executable->basic_block_list.at(bb_i));
3502 }
3503
3504 irp->pending.deinit();
3505 irp->printed.deinit();
3506}
3507
3508void ir_print_inst_src(CodeGen *codegen, FILE *f, Stage1ZirInst *instruction, int indent_size) {
3509 IrPrintSrc ir_print = {};
3510 IrPrintSrc *irp = &ir_print;
3511 irp->codegen = codegen;
3512 irp->f = f;
3513 irp->indent = indent_size;
3514 irp->indent_size = indent_size;
3515
3516 ir_print_inst_src(irp, instruction, false);
3517}
3518
3519void ir_print_inst_gen(CodeGen *codegen, FILE *f, Stage1AirInst *instruction, int indent_size) {
3520 IrPrintGen ir_print = {};
3521 IrPrintGen *irp = &ir_print;
3522 irp->codegen = codegen;
3523 irp->f = f;
3524 irp->indent = indent_size;
3525 irp->indent_size = indent_size;
3526 irp->printed = {};
3527 irp->printed.init(4);
3528 irp->pending = {};
3529
3530 ir_print_inst_gen(irp, instruction, false);
3531}
3532
3533void Stage1ZirInst::dump() {
3534 Stage1ZirInst *inst = this;
3535 inst->src();
3536 if (inst->scope == nullptr) {
3537 fprintf(stderr, "(null scope)\n");
3538 } else {
3539 ir_print_inst_src(inst->scope->codegen, stderr, inst, 0);
3540 fprintf(stderr, "-> ");
3541 ir_print_inst_gen(inst->scope->codegen, stderr, inst->child, 0);
3542 }
3543}
src/stage1/ir_print.hpp deleted-25
...@@ -1,25 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_IR_PRINT_HPP
9#define ZIG_IR_PRINT_HPP
10
11#include "all_types.hpp"
12
13#include <stdio.h>
14
15void ir_print_src(CodeGen *codegen, FILE *f, Stage1Zir *executable, int indent_size);
16void ir_print_gen(CodeGen *codegen, FILE *f, Stage1Air *executable, int indent_size);
17void ir_print_inst_src(CodeGen *codegen, FILE *f, Stage1ZirInst *inst, int indent_size);
18void ir_print_inst_gen(CodeGen *codegen, FILE *f, Stage1AirInst *inst, int indent_size);
19void ir_print_basic_block_src(CodeGen *codegen, FILE *f, Stage1ZirBasicBlock *bb, int indent_size);
20void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, Stage1AirBasicBlock *bb, int indent_size);
21
22const char* ir_inst_src_type_str(Stage1ZirInstId id);
23const char* ir_inst_gen_type_str(Stage1AirInstId id);
24
25#endif
src/stage1/list.hpp deleted-96
...@@ -1,96 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_LIST_HPP
9#define ZIG_LIST_HPP
10
11#include "util.hpp"
12
13template<typename T>
14struct ZigList {
15 void deinit() {
16 heap::c_allocator.deallocate(items, capacity);
17 }
18 void append(const T& item) {
19 ensure_capacity(length + 1);
20 items[length++] = item;
21 }
22 void append_assuming_capacity(const T& item) {
23 items[length++] = item;
24 }
25 // remember that the pointer to this item is invalid after you
26 // modify the length of the list
27 const T & at(size_t index) const {
28 assert(index != SIZE_MAX);
29 assert(index < length);
30 return items[index];
31 }
32 T & at(size_t index) {
33 assert(index != SIZE_MAX);
34 assert(index < length);
35 return items[index];
36 }
37 T pop() {
38 assert(length >= 1);
39 return items[--length];
40 }
41
42 T *add_one() {
43 resize(length + 1);
44 return &last();
45 }
46
47 const T & last() const {
48 assert(length >= 1);
49 return items[length - 1];
50 }
51
52 T & last() {
53 assert(length >= 1);
54 return items[length - 1];
55 }
56
57 void resize(size_t new_length) {
58 assert(new_length != SIZE_MAX);
59 ensure_capacity(new_length);
60 length = new_length;
61 }
62
63 void clear() {
64 length = 0;
65 }
66
67 void ensure_capacity(size_t new_capacity) {
68 if (capacity >= new_capacity)
69 return;
70
71 size_t better_capacity = capacity;
72 do {
73 better_capacity = better_capacity * 5 / 2 + 8;
74 } while (better_capacity < new_capacity);
75
76 items = heap::c_allocator.reallocate_nonzero(items, capacity, better_capacity);
77 capacity = better_capacity;
78 }
79
80 T swap_remove(size_t index) {
81 if (length - 1 == index) return pop();
82
83 assert(index != SIZE_MAX);
84 assert(index < length);
85
86 T old_item = items[index];
87 items[index] = pop();
88 return old_item;
89 }
90
91 T *items;
92 size_t length;
93 size_t capacity;
94};
95
96#endif
src/stage1/mem.cpp deleted-23
...@@ -1,23 +0,0 @@
1/*
2 * Copyright (c) 2020 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "mem.hpp"
9#include "heap.hpp"
10
11namespace mem {
12
13void init() {
14 heap::bootstrap_allocator_state.init("heap::bootstrap_allocator");
15 heap::c_allocator_state.init("heap::c_allocator");
16}
17
18void deinit() {
19 heap::c_allocator_state.deinit();
20 heap::bootstrap_allocator_state.deinit();
21}
22
23} // namespace mem
src/stage1/mem.hpp deleted-139
...@@ -1,139 +0,0 @@
1/*
2 * Copyright (c) 2020 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_MEM_HPP
9#define ZIG_MEM_HPP
10
11#include <stdint.h>
12#include <stdio.h>
13#include <stdlib.h>
14
15#include "util_base.hpp"
16#include "mem_type_info.hpp"
17
18//
19// -- Memory Allocation General Notes --
20//
21// `heap::c_allocator` is the preferred general allocator.
22//
23// `heap::bootstrap_allocator` is an implementation detail for use
24// by allocators themselves when incidental heap may be required for
25// profiling and statistics. It breaks the infinite recursion cycle.
26//
27// `mem::os` contains a raw wrapper for system malloc API used in
28// preference to calling ::{malloc, free, calloc, realloc} directly.
29// This isolates usage and helps with audits:
30//
31// mem::os::malloc
32// mem::os::free
33// mem::os::calloc
34// mem::os::realloc
35//
36namespace mem {
37
38// initialize mem module before any use
39void init();
40
41// deinitialize mem module to free memory and print report
42void deinit();
43
44// isolate system/libc allocators
45namespace os {
46
47ATTRIBUTE_RETURNS_NOALIAS
48inline void *malloc(size_t size) {
49#ifndef NDEBUG
50 // make behavior when size == 0 portable
51 if (size == 0)
52 return nullptr;
53#endif
54 auto ptr = ::malloc(size);
55 if (ptr == nullptr)
56 zig_panic("allocation failed");
57 return ptr;
58}
59
60inline void free(void *ptr) {
61 ::free(ptr);
62}
63
64ATTRIBUTE_RETURNS_NOALIAS
65inline void *calloc(size_t count, size_t size) {
66#ifndef NDEBUG
67 // make behavior when size == 0 portable
68 if (count == 0 || size == 0)
69 return nullptr;
70#endif
71 auto ptr = ::calloc(count, size);
72 if (ptr == nullptr)
73 zig_panic("allocation failed");
74 return ptr;
75}
76
77inline void *realloc(void *old_ptr, size_t size) {
78#ifndef NDEBUG
79 // make behavior when size == 0 portable
80 if (old_ptr == nullptr && size == 0)
81 return nullptr;
82#endif
83 auto ptr = ::realloc(old_ptr, size);
84 if (ptr == nullptr)
85 zig_panic("allocation failed");
86 return ptr;
87}
88
89} // namespace os
90
91struct Allocator {
92 virtual void destruct(Allocator *allocator) = 0;
93
94 template <typename T> ATTRIBUTE_RETURNS_NOALIAS
95 T *allocate(size_t count) {
96 return reinterpret_cast<T *>(this->internal_allocate(TypeInfo::make<T>(), count));
97 }
98
99 template <typename T> ATTRIBUTE_RETURNS_NOALIAS
100 T *allocate_nonzero(size_t count) {
101 return reinterpret_cast<T *>(this->internal_allocate_nonzero(TypeInfo::make<T>(), count));
102 }
103
104 template <typename T>
105 T *reallocate(T *old_ptr, size_t old_count, size_t new_count) {
106 return reinterpret_cast<T *>(this->internal_reallocate(TypeInfo::make<T>(), old_ptr, old_count, new_count));
107 }
108
109 template <typename T>
110 T *reallocate_nonzero(T *old_ptr, size_t old_count, size_t new_count) {
111 return reinterpret_cast<T *>(this->internal_reallocate_nonzero(TypeInfo::make<T>(), old_ptr, old_count, new_count));
112 }
113
114 template<typename T>
115 void deallocate(T *ptr, size_t count) {
116 this->internal_deallocate(TypeInfo::make<T>(), ptr, count);
117 }
118
119 template<typename T>
120 T *create() {
121 return reinterpret_cast<T *>(this->internal_allocate(TypeInfo::make<T>(), 1));
122 }
123
124 template<typename T>
125 void destroy(T *ptr) {
126 this->internal_deallocate(TypeInfo::make<T>(), ptr, 1);
127 }
128
129protected:
130 ATTRIBUTE_RETURNS_NOALIAS virtual void *internal_allocate(const TypeInfo &info, size_t count) = 0;
131 ATTRIBUTE_RETURNS_NOALIAS virtual void *internal_allocate_nonzero(const TypeInfo &info, size_t count) = 0;
132 virtual void *internal_reallocate(const TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) = 0;
133 virtual void *internal_reallocate_nonzero(const TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) = 0;
134 virtual void internal_deallocate(const TypeInfo &info, void *ptr, size_t count) = 0;
135};
136
137} // namespace mem
138
139#endif
src/stage1/mem_hash_map.hpp deleted-244
...@@ -1,244 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_MEM_HASH_MAP_HPP
9#define ZIG_MEM_HASH_MAP_HPP
10
11#include "mem.hpp"
12
13namespace mem {
14
15template<typename K, typename V, uint32_t (*HashFunction)(K key), bool (*EqualFn)(K a, K b)>
16class HashMap {
17public:
18 void init(Allocator& allocator, int capacity) {
19 init_capacity(allocator, capacity);
20 }
21 void deinit(Allocator& allocator) {
22 allocator.deallocate(_entries, _capacity);
23 }
24
25 struct Entry {
26 K key;
27 V value;
28 bool used;
29 int distance_from_start_index;
30 };
31
32 void clear() {
33 for (int i = 0; i < _capacity; i += 1) {
34 _entries[i].used = false;
35 }
36 _size = 0;
37 _max_distance_from_start_index = 0;
38 _modification_count += 1;
39 }
40
41 int size() const {
42 return _size;
43 }
44
45 void put(Allocator& allocator, const K &key, const V &value) {
46 _modification_count += 1;
47 internal_put(key, value);
48
49 // if we get too full (60%), double the capacity
50 if (_size * 5 >= _capacity * 3) {
51 Entry *old_entries = _entries;
52 int old_capacity = _capacity;
53 init_capacity(allocator, _capacity * 2);
54 // dump all of the old elements into the new table
55 for (int i = 0; i < old_capacity; i += 1) {
56 Entry *old_entry = &old_entries[i];
57 if (old_entry->used)
58 internal_put(old_entry->key, old_entry->value);
59 }
60 allocator.deallocate(old_entries, old_capacity);
61 }
62 }
63
64 Entry *put_unique(Allocator& allocator, const K &key, const V &value) {
65 // TODO make this more efficient
66 Entry *entry = internal_get(key);
67 if (entry)
68 return entry;
69 put(allocator, key, value);
70 return nullptr;
71 }
72
73 const V &get(const K &key) const {
74 Entry *entry = internal_get(key);
75 if (!entry)
76 zig_panic("key not found");
77 return entry->value;
78 }
79
80 Entry *maybe_get(const K &key) const {
81 return internal_get(key);
82 }
83
84 void maybe_remove(const K &key) {
85 if (maybe_get(key)) {
86 remove(key);
87 }
88 }
89
90 void remove(const K &key) {
91 _modification_count += 1;
92 int start_index = key_to_index(key);
93 for (int roll_over = 0; roll_over <= _max_distance_from_start_index; roll_over += 1) {
94 int index = (start_index + roll_over) % _capacity;
95 Entry *entry = &_entries[index];
96
97 if (!entry->used)
98 zig_panic("key not found");
99
100 if (!EqualFn(entry->key, key))
101 continue;
102
103 for (; roll_over < _capacity; roll_over += 1) {
104 int next_index = (start_index + roll_over + 1) % _capacity;
105 Entry *next_entry = &_entries[next_index];
106 if (!next_entry->used || next_entry->distance_from_start_index == 0) {
107 entry->used = false;
108 _size -= 1;
109 return;
110 }
111 *entry = *next_entry;
112 entry->distance_from_start_index -= 1;
113 entry = next_entry;
114 }
115 zig_panic("shifting everything in the table");
116 }
117 zig_panic("key not found");
118 }
119
120 class Iterator {
121 public:
122 Entry *next() {
123 if (_inital_modification_count != _table->_modification_count)
124 zig_panic("concurrent modification");
125 if (_count >= _table->size())
126 return NULL;
127 for (; _index < _table->_capacity; _index += 1) {
128 Entry *entry = &_table->_entries[_index];
129 if (entry->used) {
130 _index += 1;
131 _count += 1;
132 return entry;
133 }
134 }
135 zig_panic("no next item");
136 }
137
138 private:
139 const HashMap * _table;
140 // how many items have we returned
141 int _count = 0;
142 // iterator through the entry array
143 int _index = 0;
144 // used to detect concurrent modification
145 uint32_t _inital_modification_count;
146 Iterator(const HashMap * table) :
147 _table(table), _inital_modification_count(table->_modification_count) {
148 }
149 friend HashMap;
150 };
151
152 // you must not modify the underlying HashMap while this iterator is still in use
153 Iterator entry_iterator() const {
154 return Iterator(this);
155 }
156
157private:
158 Entry *_entries;
159 int _capacity;
160 int _size;
161 int _max_distance_from_start_index;
162 // this is used to detect bugs where a hashtable is edited while an iterator is running.
163 uint32_t _modification_count;
164
165 void init_capacity(Allocator& allocator, int capacity) {
166 _capacity = capacity;
167 _entries = allocator.allocate<Entry>(_capacity);
168 _size = 0;
169 _max_distance_from_start_index = 0;
170 for (int i = 0; i < _capacity; i += 1) {
171 _entries[i].used = false;
172 }
173 }
174
175 void internal_put(K key, V value) {
176 int start_index = key_to_index(key);
177 for (int roll_over = 0, distance_from_start_index = 0;
178 roll_over < _capacity; roll_over += 1, distance_from_start_index += 1)
179 {
180 int index = (start_index + roll_over) % _capacity;
181 Entry *entry = &_entries[index];
182
183 if (entry->used && !EqualFn(entry->key, key)) {
184 if (entry->distance_from_start_index < distance_from_start_index) {
185 // robin hood to the rescue
186 Entry tmp = *entry;
187 if (distance_from_start_index > _max_distance_from_start_index)
188 _max_distance_from_start_index = distance_from_start_index;
189 *entry = {
190 key,
191 value,
192 true,
193 distance_from_start_index,
194 };
195 key = tmp.key;
196 value = tmp.value;
197 distance_from_start_index = tmp.distance_from_start_index;
198 }
199 continue;
200 }
201
202 if (!entry->used) {
203 // adding an entry. otherwise overwriting old value with
204 // same key
205 _size += 1;
206 }
207
208 if (distance_from_start_index > _max_distance_from_start_index)
209 _max_distance_from_start_index = distance_from_start_index;
210 *entry = {
211 key,
212 value,
213 true,
214 distance_from_start_index,
215 };
216 return;
217 }
218 zig_panic("put into a full HashMap");
219 }
220
221
222 Entry *internal_get(const K &key) const {
223 int start_index = key_to_index(key);
224 for (int roll_over = 0; roll_over <= _max_distance_from_start_index; roll_over += 1) {
225 int index = (start_index + roll_over) % _capacity;
226 Entry *entry = &_entries[index];
227
228 if (!entry->used)
229 return NULL;
230
231 if (EqualFn(entry->key, key))
232 return entry;
233 }
234 return NULL;
235 }
236
237 int key_to_index(const K &key) const {
238 return (int)(HashFunction(key) % ((uint32_t)_capacity));
239 }
240};
241
242} // namespace mem
243
244#endif
src/stage1/mem_list.hpp deleted-104
...@@ -1,104 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_MEM_LIST_HPP
9#define ZIG_MEM_LIST_HPP
10
11#include "mem.hpp"
12
13namespace mem {
14
15template<typename T>
16struct List {
17 void deinit(Allocator *allocator) {
18 allocator->deallocate<T>(items, capacity);
19 items = nullptr;
20 length = 0;
21 capacity = 0;
22 }
23
24 void append(Allocator *allocator, const T& item) {
25 ensure_capacity(allocator, length + 1);
26 items[length++] = item;
27 }
28
29 // remember that the pointer to this item is invalid after you
30 // modify the length of the list
31 const T & at(size_t index) const {
32 assert(index != SIZE_MAX);
33 assert(index < length);
34 return items[index];
35 }
36
37 T & at(size_t index) {
38 assert(index != SIZE_MAX);
39 assert(index < length);
40 return items[index];
41 }
42
43 T pop() {
44 assert(length >= 1);
45 return items[--length];
46 }
47
48 T *add_one() {
49 resize(length + 1);
50 return &last();
51 }
52
53 const T & last() const {
54 assert(length >= 1);
55 return items[length - 1];
56 }
57
58 T & last() {
59 assert(length >= 1);
60 return items[length - 1];
61 }
62
63 void resize(Allocator *allocator, size_t new_length) {
64 assert(new_length != SIZE_MAX);
65 ensure_capacity(allocator, new_length);
66 length = new_length;
67 }
68
69 void clear() {
70 length = 0;
71 }
72
73 void ensure_capacity(Allocator *allocator, size_t new_capacity) {
74 if (capacity >= new_capacity)
75 return;
76
77 size_t better_capacity = capacity;
78 do {
79 better_capacity = better_capacity * 5 / 2 + 8;
80 } while (better_capacity < new_capacity);
81
82 items = allocator->reallocate_nonzero<T>(items, capacity, better_capacity);
83 capacity = better_capacity;
84 }
85
86 T swap_remove(size_t index) {
87 if (length - 1 == index) return pop();
88
89 assert(index != SIZE_MAX);
90 assert(index < length);
91
92 T old_item = items[index];
93 items[index] = pop();
94 return old_item;
95 }
96
97 T *items{nullptr};
98 size_t length{0};
99 size_t capacity{0};
100};
101
102} // namespace mem
103
104#endif
src/stage1/mem_type_info.hpp deleted-25
...@@ -1,25 +0,0 @@
1/*
2 * Copyright (c) 2020 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_MEM_TYPE_INFO_HPP
9#define ZIG_MEM_TYPE_INFO_HPP
10
11namespace mem {
12
13struct TypeInfo {
14 size_t size;
15 size_t alignment;
16
17 template <typename T>
18 static constexpr TypeInfo make() {
19 return {sizeof(T), alignof(T)};
20 }
21};
22
23} // namespace mem
24
25#endif
src/stage1/os.cpp deleted-1282
...@@ -1,1282 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "os.hpp"
9#include "buffer.hpp"
10#include "heap.hpp"
11#include "util.hpp"
12#include "error.hpp"
13#include "util_base.hpp"
14#include <stdint.h>
15#include <stdio.h>
16
17#if defined(_WIN32)
18
19#if !defined(NOMINMAX)
20#define NOMINMAX
21#endif
22
23#if !defined(VC_EXTRALEAN)
24#define VC_EXTRALEAN
25#endif
26
27#if !defined(WIN32_LEAN_AND_MEAN)
28#define WIN32_LEAN_AND_MEAN
29#endif
30
31#if !defined(_WIN32_WINNT)
32#define _WIN32_WINNT 0x600
33#endif
34
35#if !defined(NTDDI_VERSION)
36#define NTDDI_VERSION 0x06000000
37#endif
38
39#include <windows.h>
40#include <shlobj.h>
41#include <io.h>
42#include <fcntl.h>
43#include <ntsecapi.h>
44#include <math.h>
45
46// Workaround an upstream LLVM issue.
47// See https://github.com/ziglang/zig/issues/7614#issuecomment-752939981
48#if defined(_MSC_VER) && defined(_WIN64)
49typedef SSIZE_T ssize_t;
50#endif
51#else
52#define ZIG_OS_POSIX
53
54#include <unistd.h>
55#include <sys/types.h>
56#include <sys/stat.h>
57#include <sys/wait.h>
58#include <sys/resource.h>
59#include <fcntl.h>
60#include <limits.h>
61#include <spawn.h>
62
63#endif
64
65#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY) || defined(ZIG_OS_OPENBSD) || defined(ZIG_OS_HAIKU)
66#include <link.h>
67#endif
68
69#if defined(ZIG_OS_LINUX)
70#include <sys/auxv.h>
71#endif
72
73#if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY) || defined(ZIG_OS_OPENBSD)
74#include <sys/sysctl.h>
75#endif
76
77#if defined(__MACH__)
78#include <mach/clock.h>
79#include <mach/mach.h>
80#include <mach-o/dyld.h>
81#endif
82
83#if defined(ZIG_OS_WINDOWS)
84static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le);
85static size_t utf8_to_utf16le(WCHAR *utf16_le, Slice<uint8_t> utf8);
86static uint64_t windows_perf_freq;
87#elif defined(__MACH__)
88static clock_serv_t macos_calendar_clock;
89static clock_serv_t macos_monotonic_clock;
90#endif
91
92#include <stdlib.h>
93#include <errno.h>
94#include <time.h>
95
96#if !defined(environ)
97extern char **environ;
98#endif
99
100void os_path_dirname(Buf *full_path, Buf *out_dirname) {
101 return os_path_split(full_path, out_dirname, nullptr);
102}
103
104bool os_is_sep(uint8_t c) {
105#if defined(ZIG_OS_WINDOWS)
106 return c == '\\' || c == '/';
107#else
108 return c == '/';
109#endif
110}
111
112void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) {
113 size_t len = buf_len(full_path);
114 if (len != 0) {
115 size_t last_index = len - 1;
116 char last_char = buf_ptr(full_path)[last_index];
117 if (os_is_sep(last_char)) {
118 if (last_index == 0) {
119 if (out_dirname) buf_init_from_mem(out_dirname, &last_char, 1);
120 if (out_basename) buf_init_from_str(out_basename, "");
121 return;
122 }
123 last_index -= 1;
124 }
125 for (size_t i = last_index;;) {
126 uint8_t c = buf_ptr(full_path)[i];
127 if (os_is_sep(c)) {
128 if (out_dirname) {
129 buf_init_from_mem(out_dirname, buf_ptr(full_path), (i == 0) ? 1 : i);
130 }
131 if (out_basename) {
132 buf_init_from_mem(out_basename, buf_ptr(full_path) + i + 1, buf_len(full_path) - (i + 1));
133 }
134 return;
135 }
136 if (i == 0) break;
137 i -= 1;
138 }
139 }
140 if (out_dirname) buf_init_from_mem(out_dirname, ".", 1);
141 if (out_basename) buf_init_from_buf(out_basename, full_path);
142}
143
144void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname) {
145 if (buf_len(full_path) == 0) {
146 if (out_basename) buf_init_from_str(out_basename, "");
147 if (out_extname) buf_init_from_str(out_extname, "");
148 return;
149 }
150 size_t i = buf_len(full_path) - 1;
151 while (true) {
152 if (buf_ptr(full_path)[i] == '.') {
153 if (out_basename) {
154 buf_resize(out_basename, 0);
155 buf_append_mem(out_basename, buf_ptr(full_path), i);
156 }
157
158 if (out_extname) {
159 buf_resize(out_extname, 0);
160 buf_append_mem(out_extname, buf_ptr(full_path) + i, buf_len(full_path) - i);
161 }
162 return;
163 }
164
165 if (i == 0) {
166 if (out_basename) buf_init_from_buf(out_basename, full_path);
167 if (out_extname) buf_init_from_str(out_extname, "");
168 return;
169 }
170 i -= 1;
171 }
172}
173
174void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
175 if (buf_len(dirname) == 0) {
176 buf_init_from_buf(out_full_path, basename);
177 return;
178 }
179
180 buf_init_from_buf(out_full_path, dirname);
181 uint8_t c = *(buf_ptr(out_full_path) + buf_len(out_full_path) - 1);
182 if (!os_is_sep(c))
183 buf_append_char(out_full_path, ZIG_OS_SEP_CHAR);
184 buf_append_buf(out_full_path, basename);
185}
186
187
188#if defined(ZIG_OS_WINDOWS)
189// Ported from std/os/path.zig
190static bool isAbsoluteWindows(Slice<uint8_t> path) {
191 if (path.ptr[0] == '/')
192 return true;
193
194 if (path.ptr[0] == '\\') {
195 return true;
196 }
197 if (path.len < 3) {
198 return false;
199 }
200 if (path.ptr[1] == ':') {
201 if (path.ptr[2] == '/')
202 return true;
203 if (path.ptr[2] == '\\')
204 return true;
205 }
206 return false;
207}
208
209enum WindowsPathKind {
210 WindowsPathKindNone,
211 WindowsPathKindDrive,
212 WindowsPathKindNetworkShare,
213};
214
215struct WindowsPath {
216 Slice<uint8_t> disk_designator;
217 WindowsPathKind kind;
218 bool is_abs;
219};
220
221
222// Ported from std/os/path.zig
223static WindowsPath windowsParsePath(Slice<uint8_t> path) {
224 if (path.len >= 2 && path.ptr[1] == ':') {
225 return WindowsPath{
226 path.slice(0, 2),
227 WindowsPathKindDrive,
228 isAbsoluteWindows(path),
229 };
230 }
231 if (path.len >= 1 && (path.ptr[0] == '/' || path.ptr[0] == '\\') &&
232 (path.len == 1 || (path.ptr[1] != '/' && path.ptr[1] != '\\')))
233 {
234 return WindowsPath{
235 path.slice(0, 0),
236 WindowsPathKindNone,
237 true,
238 };
239 }
240 WindowsPath relative_path = {
241 str(""),
242 WindowsPathKindNone,
243 false,
244 };
245 if (path.len < strlen("//a/b")) {
246 return relative_path;
247 }
248
249 {
250 if (memStartsWith(path, str("//"))) {
251 if (path.ptr[2] == '/') {
252 return relative_path;
253 }
254
255 SplitIterator it = memSplit(path, str("/"));
256 {
257 Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
258 if (!opt_component.is_some) return relative_path;
259 }
260 {
261 Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
262 if (!opt_component.is_some) return relative_path;
263 }
264 return WindowsPath{
265 path.slice(0, it.index),
266 WindowsPathKindNetworkShare,
267 isAbsoluteWindows(path),
268 };
269 }
270 }
271 {
272 if (memStartsWith(path, str("\\\\"))) {
273 if (path.ptr[2] == '\\') {
274 return relative_path;
275 }
276
277 SplitIterator it = memSplit(path, str("\\"));
278 {
279 Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
280 if (!opt_component.is_some) return relative_path;
281 }
282 {
283 Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
284 if (!opt_component.is_some) return relative_path;
285 }
286 return WindowsPath{
287 path.slice(0, it.index),
288 WindowsPathKindNetworkShare,
289 isAbsoluteWindows(path),
290 };
291 }
292 }
293 return relative_path;
294}
295
296// Ported from std/os/path.zig
297static uint8_t asciiUpper(uint8_t byte) {
298 if (byte >= 'a' && byte <= 'z') {
299 return 'A' + (byte - 'a');
300 }
301 return byte;
302}
303
304// Ported from std/os/path.zig
305static bool asciiEqlIgnoreCase(Slice<uint8_t> s1, Slice<uint8_t> s2) {
306 if (s1.len != s2.len)
307 return false;
308 for (size_t i = 0; i < s1.len; i += 1) {
309 if (asciiUpper(s1.ptr[i]) != asciiUpper(s2.ptr[i]))
310 return false;
311 }
312 return true;
313}
314
315// Ported from std/os/path.zig
316static bool compareDiskDesignators(WindowsPathKind kind, Slice<uint8_t> p1, Slice<uint8_t> p2) {
317 switch (kind) {
318 case WindowsPathKindNone:
319 assert(p1.len == 0);
320 assert(p2.len == 0);
321 return true;
322 case WindowsPathKindDrive:
323 return asciiUpper(p1.ptr[0]) == asciiUpper(p2.ptr[0]);
324 case WindowsPathKindNetworkShare:
325 uint8_t sep1 = p1.ptr[0];
326 uint8_t sep2 = p2.ptr[0];
327
328 SplitIterator it1 = memSplit(p1, {&sep1, 1});
329 SplitIterator it2 = memSplit(p2, {&sep2, 1});
330
331 // TODO ASCII is wrong, we actually need full unicode support to compare paths.
332 return asciiEqlIgnoreCase(SplitIterator_next(&it1).value, SplitIterator_next(&it2).value) &&
333 asciiEqlIgnoreCase(SplitIterator_next(&it1).value, SplitIterator_next(&it2).value);
334 }
335 zig_unreachable();
336}
337
338// Ported from std/os/path.zig
339static Buf os_path_resolve_windows(Buf **paths_ptr, size_t paths_len) {
340 if (paths_len == 0) {
341 Buf cwd = BUF_INIT;
342 int err;
343 if ((err = os_get_cwd(&cwd))) {
344 zig_panic("get cwd failed");
345 }
346 return cwd;
347 }
348
349 // determine which disk designator we will result with, if any
350 char result_drive_buf[3] = {'_', ':', '\0'}; // 0 needed for strlen later
351 Slice<uint8_t> result_disk_designator = str("");
352 WindowsPathKind have_drive_kind = WindowsPathKindNone;
353 bool have_abs_path = false;
354 size_t first_index = 0;
355 size_t max_size = 0;
356 for (size_t i = 0; i < paths_len; i += 1) {
357 Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
358 WindowsPath parsed = windowsParsePath(p);
359 if (parsed.is_abs) {
360 have_abs_path = true;
361 first_index = i;
362 max_size = result_disk_designator.len;
363 }
364 switch (parsed.kind) {
365 case WindowsPathKindDrive:
366 result_drive_buf[0] = asciiUpper(parsed.disk_designator.ptr[0]);
367 result_disk_designator = str(result_drive_buf);
368 have_drive_kind = WindowsPathKindDrive;
369 break;
370 case WindowsPathKindNetworkShare:
371 result_disk_designator = parsed.disk_designator;
372 have_drive_kind = WindowsPathKindNetworkShare;
373 break;
374 case WindowsPathKindNone:
375 break;
376 }
377 max_size += p.len + 1;
378 }
379
380 // if we will result with a disk designator, loop again to determine
381 // which is the last time the disk designator is absolutely specified, if any
382 // and count up the max bytes for paths related to this disk designator
383 if (have_drive_kind != WindowsPathKindNone) {
384 have_abs_path = false;
385 first_index = 0;
386 max_size = result_disk_designator.len;
387 bool correct_disk_designator = false;
388
389 for (size_t i = 0; i < paths_len; i += 1) {
390 Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
391 WindowsPath parsed = windowsParsePath(p);
392 if (parsed.kind != WindowsPathKindNone) {
393 if (parsed.kind == have_drive_kind) {
394 correct_disk_designator = compareDiskDesignators(have_drive_kind, result_disk_designator, parsed.disk_designator);
395 } else {
396 continue;
397 }
398 }
399 if (!correct_disk_designator) {
400 continue;
401 }
402 if (parsed.is_abs) {
403 first_index = i;
404 max_size = result_disk_designator.len;
405 have_abs_path = true;
406 }
407 max_size += p.len + 1;
408 }
409 }
410
411 // Allocate result and fill in the disk designator, calling getCwd if we have to.
412 Slice<uint8_t> result;
413 size_t result_index = 0;
414
415 if (have_abs_path) {
416 switch (have_drive_kind) {
417 case WindowsPathKindDrive: {
418 result = Slice<uint8_t>::alloc(max_size);
419
420 memCopy(result, result_disk_designator);
421 result_index += result_disk_designator.len;
422 break;
423 }
424 case WindowsPathKindNetworkShare: {
425 result = Slice<uint8_t>::alloc(max_size);
426 SplitIterator it = memSplit(buf_to_slice(paths_ptr[first_index]), str("/\\"));
427 Slice<uint8_t> server_name = SplitIterator_next(&it).value;
428 Slice<uint8_t> other_name = SplitIterator_next(&it).value;
429
430 result.ptr[result_index] = '\\';
431 result_index += 1;
432 result.ptr[result_index] = '\\';
433 result_index += 1;
434 memCopy(result.sliceFrom(result_index), server_name);
435 result_index += server_name.len;
436 result.ptr[result_index] = '\\';
437 result_index += 1;
438 memCopy(result.sliceFrom(result_index), other_name);
439 result_index += other_name.len;
440
441 result_disk_designator = result.slice(0, result_index);
442 break;
443 }
444 case WindowsPathKindNone: {
445 Buf cwd = BUF_INIT;
446 int err;
447 if ((err = os_get_cwd(&cwd))) {
448 zig_panic("get cwd failed");
449 }
450 WindowsPath parsed_cwd = windowsParsePath(buf_to_slice(&cwd));
451 result = Slice<uint8_t>::alloc(max_size + parsed_cwd.disk_designator.len + 1);
452 memCopy(result, parsed_cwd.disk_designator);
453 result_index += parsed_cwd.disk_designator.len;
454 result_disk_designator = result.slice(0, parsed_cwd.disk_designator.len);
455 if (parsed_cwd.kind == WindowsPathKindDrive) {
456 result.ptr[0] = asciiUpper(result.ptr[0]);
457 }
458 have_drive_kind = parsed_cwd.kind;
459 break;
460 }
461 }
462 } else {
463 // TODO call get cwd for the result_disk_designator instead of the global one
464 Buf cwd = BUF_INIT;
465 int err;
466 if ((err = os_get_cwd(&cwd))) {
467 zig_panic("get cwd failed");
468 }
469 result = Slice<uint8_t>::alloc(max_size + buf_len(&cwd) + 1);
470
471 memCopy(result, buf_to_slice(&cwd));
472 result_index += buf_len(&cwd);
473 WindowsPath parsed_cwd = windowsParsePath(result.slice(0, result_index));
474 result_disk_designator = parsed_cwd.disk_designator;
475 if (parsed_cwd.kind == WindowsPathKindDrive) {
476 result.ptr[0] = asciiUpper(result.ptr[0]);
477 // Remove the trailing slash if present, eg. if the cwd is a root
478 // directory.
479 if (buf_ends_with_mem(&cwd, "\\", 1)) {
480 result_index -= 1;
481 }
482 }
483 have_drive_kind = parsed_cwd.kind;
484 }
485
486 // Now we know the disk designator to use, if any, and what kind it is. And our result
487 // is big enough to append all the paths to.
488 bool correct_disk_designator = true;
489 for (size_t i = first_index; i < paths_len; i += 1) {
490 Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
491 WindowsPath parsed = windowsParsePath(p);
492
493 if (parsed.kind != WindowsPathKindNone) {
494 if (parsed.kind == have_drive_kind) {
495 correct_disk_designator = compareDiskDesignators(have_drive_kind, result_disk_designator, parsed.disk_designator);
496 } else {
497 continue;
498 }
499 }
500 if (!correct_disk_designator) {
501 continue;
502 }
503 SplitIterator it = memSplit(p.sliceFrom(parsed.disk_designator.len), str("/\\"));
504 while (true) {
505 Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
506 if (!opt_component.is_some) break;
507 Slice<uint8_t> component = opt_component.value;
508 if (memEql(component, str("."))) {
509 continue;
510 } else if (memEql(component, str(".."))) {
511 while (true) {
512 if (result_index == 0 || result_index == result_disk_designator.len)
513 break;
514 result_index -= 1;
515 if (result.ptr[result_index] == '\\' || result.ptr[result_index] == '/')
516 break;
517 }
518 } else {
519 result.ptr[result_index] = '\\';
520 result_index += 1;
521 memCopy(result.sliceFrom(result_index), component);
522 result_index += component.len;
523 }
524 }
525 }
526
527 if (result_index == result_disk_designator.len) {
528 result.ptr[result_index] = '\\';
529 result_index += 1;
530 }
531
532 Buf return_value = BUF_INIT;
533 buf_init_from_mem(&return_value, (char *)result.ptr, result_index);
534 return return_value;
535}
536#endif
537
538#if defined(ZIG_OS_POSIX)
539// Ported from std/os/path.zig
540static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) {
541 if (paths_len == 0) {
542 Buf cwd = BUF_INIT;
543 int err;
544 if ((err = os_get_cwd(&cwd))) {
545 zig_panic("get cwd failed");
546 }
547 return cwd;
548 }
549
550 size_t first_index = 0;
551 bool have_abs = false;
552 size_t max_size = 0;
553 for (size_t i = 0; i < paths_len; i += 1) {
554 Buf *p = paths_ptr[i];
555 if (buf_ptr(p)[0] == '/') {
556 first_index = i;
557 have_abs = true;
558 max_size = 0;
559 }
560 max_size += buf_len(p) + 1;
561 }
562
563 uint8_t *result_ptr;
564 size_t result_len;
565 size_t result_index = 0;
566
567 if (have_abs) {
568 result_len = max_size;
569 result_ptr = heap::c_allocator.allocate_nonzero<uint8_t>(result_len);
570 } else {
571 Buf cwd = BUF_INIT;
572 int err;
573 if ((err = os_get_cwd(&cwd))) {
574 zig_panic("get cwd failed");
575 }
576 result_len = max_size + buf_len(&cwd) + 1;
577 result_ptr = heap::c_allocator.allocate_nonzero<uint8_t>(result_len);
578 memcpy(result_ptr, buf_ptr(&cwd), buf_len(&cwd));
579 result_index += buf_len(&cwd);
580 }
581
582 for (size_t i = first_index; i < paths_len; i += 1) {
583 Buf *p = paths_ptr[i];
584 SplitIterator it = memSplit(buf_to_slice(p), str("/"));
585 while (true) {
586 Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
587 if (!opt_component.is_some) break;
588 Slice<uint8_t> component = opt_component.value;
589
590 if (memEql<uint8_t>(component, str("."))) {
591 continue;
592 } else if (memEql<uint8_t>(component, str(".."))) {
593 while (true) {
594 if (result_index == 0)
595 break;
596 result_index -= 1;
597 if (result_ptr[result_index] == '/')
598 break;
599 }
600 } else {
601 result_ptr[result_index] = '/';
602 result_index += 1;
603 memcpy(result_ptr + result_index, component.ptr, component.len);
604 result_index += component.len;
605 }
606 }
607 }
608
609 if (result_index == 0) {
610 result_ptr[0] = '/';
611 result_index += 1;
612 }
613
614 Buf return_value = BUF_INIT;
615 buf_init_from_mem(&return_value, (char *)result_ptr, result_index);
616 heap::c_allocator.deallocate(result_ptr, result_len);
617 return return_value;
618}
619#endif
620
621// Ported from std/os/path.zig
622Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) {
623#if defined(ZIG_OS_WINDOWS)
624 return os_path_resolve_windows(paths_ptr, paths_len);
625#elif defined(ZIG_OS_POSIX)
626 return os_path_resolve_posix(paths_ptr, paths_len);
627#else
628#error "missing os_path_resolve implementation"
629#endif
630}
631
632Error os_fetch_file(FILE *f, Buf *out_buf) {
633 static const ssize_t buf_size = 0x2000;
634 buf_resize(out_buf, buf_size);
635 ssize_t actual_buf_len = 0;
636
637 for (;;) {
638 size_t amt_read = fread(buf_ptr(out_buf) + actual_buf_len, 1, buf_size, f);
639 actual_buf_len += amt_read;
640
641 if (amt_read != buf_size) {
642 if (feof(f)) {
643 buf_resize(out_buf, actual_buf_len);
644 return ErrorNone;
645 } else {
646 return ErrorFileSystem;
647 }
648 }
649
650 buf_resize(out_buf, actual_buf_len + buf_size);
651 }
652 zig_unreachable();
653}
654
655Error os_write_file(Buf *full_path, Buf *contents) {
656#if defined(ZIG_OS_WINDOWS)
657 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
658 FILE *f = _wfopen(&path_space.data.items[0], L"wb");
659#else
660 FILE *f = fopen(buf_ptr(full_path), "wb");
661#endif
662 if (!f) {
663 zig_panic("os_write_file failed for %s", buf_ptr(full_path));
664 }
665 size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f);
666 if (amt_written != (size_t)buf_len(contents))
667 zig_panic("write failed: %s", strerror(errno));
668 if (fclose(f))
669 zig_panic("close failed");
670 return ErrorNone;
671}
672
673static Error copy_open_files(FILE *src_f, FILE *dest_f) {
674 static const size_t buf_size = 2048;
675 char buf[buf_size];
676 for (;;) {
677 size_t amt_read = fread(buf, 1, buf_size, src_f);
678 if (amt_read != buf_size) {
679 if (ferror(src_f)) {
680 return ErrorFileSystem;
681 }
682 }
683 size_t amt_written = fwrite(buf, 1, amt_read, dest_f);
684 if (amt_written != amt_read) {
685 return ErrorFileSystem;
686 }
687 if (feof(src_f)) {
688 return ErrorNone;
689 }
690 }
691}
692
693Error os_copy_file(Buf *src_path, Buf *dest_path) {
694#if defined(ZIG_OS_WINDOWS)
695 PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
696 FILE *src_f = _wfopen(&src_path_space.data.items[0], L"rb");
697#else
698 FILE *src_f = fopen(buf_ptr(src_path), "rb");
699#endif
700 if (!src_f) {
701 int err = errno;
702 if (err == ENOENT) {
703 return ErrorFileNotFound;
704 } else if (err == EACCES || err == EPERM) {
705 return ErrorAccess;
706 } else {
707 return ErrorFileSystem;
708 }
709 }
710#if defined(ZIG_OS_WINDOWS)
711 PathSpace dest_path_space = slice_to_prefixed_file_w(buf_to_slice(dest_path));
712 FILE *dest_f = _wfopen(&dest_path_space.data.items[0], L"wb");
713#else
714 FILE *dest_f = fopen(buf_ptr(dest_path), "wb");
715#endif
716 if (!dest_f) {
717 int err = errno;
718 if (err == ENOENT) {
719 fclose(src_f);
720 return ErrorFileNotFound;
721 } else if (err == EACCES || err == EPERM) {
722 fclose(src_f);
723 return ErrorAccess;
724 } else {
725 fclose(src_f);
726 return ErrorFileSystem;
727 }
728 }
729 Error err = copy_open_files(src_f, dest_f);
730 fclose(src_f);
731 fclose(dest_f);
732 return err;
733}
734
735Error os_fetch_file_path(Buf *full_path, Buf *out_contents) {
736#if defined(ZIG_OS_WINDOWS)
737 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
738 FILE *f = _wfopen(&path_space.data.items[0], L"rb");
739#else
740 FILE *f = fopen(buf_ptr(full_path), "rb");
741#endif
742 if (!f) {
743 switch (errno) {
744 case EACCES:
745 return ErrorAccess;
746 case EINTR:
747 return ErrorInterrupted;
748 case EINVAL:
749 return ErrorInvalidFilename;
750 case ENFILE:
751 case ENOMEM:
752 return ErrorSystemResources;
753 case ENOENT:
754 return ErrorFileNotFound;
755 default:
756 return ErrorFileSystem;
757 }
758 }
759 Error result = os_fetch_file(f, out_contents);
760 fclose(f);
761 return result;
762}
763
764Error os_get_cwd(Buf *out_cwd) {
765#if defined(ZIG_OS_WINDOWS)
766 PathSpace path_space;
767 if (GetCurrentDirectoryW(PATH_MAX_WIDE, &path_space.data.items[0]) == 0) {
768 zig_panic("GetCurrentDirectory failed");
769 }
770 utf16le_ptr_to_utf8(out_cwd, &path_space.data.items[0]);
771 return ErrorNone;
772#elif defined(ZIG_OS_POSIX)
773 char buf[PATH_MAX];
774 char *res = getcwd(buf, PATH_MAX);
775 if (res == nullptr) {
776 zig_panic("unable to get cwd: %s", strerror(errno));
777 }
778 buf_init_from_str(out_cwd, res);
779 return ErrorNone;
780#else
781#error "missing os_get_cwd implementation"
782#endif
783}
784
785#if defined(ZIG_OS_WINDOWS)
786#define is_wprefix(s, prefix) \
787 (wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0)
788static bool is_stderr_cyg_pty(void) {
789 HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
790 if (stderr_handle == INVALID_HANDLE_VALUE)
791 return false;
792
793 const int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH;
794 FILE_NAME_INFO *nameinfo;
795 WCHAR *p = NULL;
796
797 // Cygwin/msys's pty is a pipe.
798 if (GetFileType(stderr_handle) != FILE_TYPE_PIPE) {
799 return 0;
800 }
801 nameinfo = reinterpret_cast<FILE_NAME_INFO *>(heap::c_allocator.allocate<char>(size));
802 if (nameinfo == NULL) {
803 return 0;
804 }
805 // Check the name of the pipe:
806 // '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master'
807 if (GetFileInformationByHandleEx(stderr_handle, FileNameInfo, nameinfo, size)) {
808 nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0';
809 p = nameinfo->FileName;
810 if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */
811 p += 8;
812 } else if (is_wprefix(p, L"\\msys-")) { /* MSYS and MSYS2 */
813 p += 6;
814 } else {
815 p = NULL;
816 }
817 if (p != NULL) {
818 while (*p && isxdigit(*p)) /* Skip 16-digit hexadecimal. */
819 ++p;
820 if (is_wprefix(p, L"-pty")) {
821 p += 4;
822 } else {
823 p = NULL;
824 }
825 }
826 if (p != NULL) {
827 while (*p && isdigit(*p)) /* Skip pty number. */
828 ++p;
829 if (is_wprefix(p, L"-from-master")) {
830 //p += 12;
831 } else if (is_wprefix(p, L"-to-master")) {
832 //p += 10;
833 } else {
834 p = NULL;
835 }
836 }
837 }
838 heap::c_allocator.deallocate(reinterpret_cast<char *>(nameinfo), size);
839 return (p != NULL);
840}
841#endif
842
843bool os_stderr_supports_color(void) {
844 if (getenv("NO_COLOR") != NULL) return false;
845#if defined(ZIG_OS_WINDOWS)
846 return _isatty(_fileno(stderr)) != 0 || is_stderr_cyg_pty();
847#elif defined(ZIG_OS_POSIX)
848 return isatty(STDERR_FILENO) != 0;
849#else
850#error "missing os_stderr_supports_color implementation"
851#endif
852}
853
854Error os_rename(Buf *src_path, Buf *dest_path) {
855 if (buf_eql_buf(src_path, dest_path)) {
856 return ErrorNone;
857 }
858#if defined(ZIG_OS_WINDOWS)
859 PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
860 PathSpace dest_path_space = slice_to_prefixed_file_w(buf_to_slice(dest_path));
861 if (!MoveFileExW(&src_path_space.data.items[0], &dest_path_space.data.items[0], MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
862 return ErrorFileSystem;
863 }
864#else
865 if (rename(buf_ptr(src_path), buf_ptr(dest_path)) == -1) {
866 return ErrorFileSystem;
867 }
868#endif
869 return ErrorNone;
870}
871
872OsTimeStamp os_timestamp_monotonic(void) {
873 OsTimeStamp result;
874#if defined(ZIG_OS_WINDOWS)
875 uint64_t counts;
876 QueryPerformanceCounter((LARGE_INTEGER*)&counts);
877 result.sec = counts / windows_perf_freq;
878 result.nsec = (counts % windows_perf_freq) * 1000000000u / windows_perf_freq;
879#elif defined(__MACH__)
880 mach_timespec_t mts;
881
882 kern_return_t err = clock_get_time(macos_monotonic_clock, &mts);
883 assert(!err);
884
885 result.sec = mts.tv_sec;
886 result.nsec = mts.tv_nsec;
887#else
888 struct timespec tms;
889 clock_gettime(CLOCK_MONOTONIC, &tms);
890
891 result.sec = tms.tv_sec;
892 result.nsec = tms.tv_nsec;
893#endif
894 return result;
895}
896
897Error os_make_path(Buf *path) {
898 Buf resolved_path = os_path_resolve(&path, 1);
899
900 size_t end_index = buf_len(&resolved_path);
901 Error err;
902 while (true) {
903 if ((err = os_make_dir(buf_slice(&resolved_path, 0, end_index)))) {
904 if (err == ErrorPathAlreadyExists) {
905 if (end_index == buf_len(&resolved_path))
906 return ErrorNone;
907 } else if (err == ErrorFileNotFound) {
908 // march end_index backward until next path component
909 while (true) {
910 end_index -= 1;
911 if (os_is_sep(buf_ptr(&resolved_path)[end_index]))
912 break;
913 }
914 continue;
915 } else {
916 return err;
917 }
918 }
919 if (end_index == buf_len(&resolved_path))
920 return ErrorNone;
921 // march end_index forward until next path component
922 while (true) {
923 end_index += 1;
924 if (end_index == buf_len(&resolved_path) || os_is_sep(buf_ptr(&resolved_path)[end_index]))
925 break;
926 }
927 }
928 return ErrorNone;
929}
930
931Error os_make_dir(Buf *path) {
932#if defined(ZIG_OS_WINDOWS)
933 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(path));
934
935 if (!CreateDirectoryW(&path_space.data.items[0], NULL)) {
936 if (GetLastError() == ERROR_ALREADY_EXISTS)
937 return ErrorPathAlreadyExists;
938 if (GetLastError() == ERROR_PATH_NOT_FOUND)
939 return ErrorFileNotFound;
940 if (GetLastError() == ERROR_ACCESS_DENIED)
941 return ErrorAccess;
942 return ErrorUnexpected;
943 }
944 return ErrorNone;
945#else
946 if (mkdir(buf_ptr(path), 0755) == -1) {
947 if (errno == EEXIST)
948 return ErrorPathAlreadyExists;
949 if (errno == ENOENT)
950 return ErrorFileNotFound;
951 if (errno == EACCES)
952 return ErrorAccess;
953 return ErrorUnexpected;
954 }
955 return ErrorNone;
956#endif
957}
958
959
960int os_init(void) {
961#if defined(ZIG_OS_WINDOWS)
962 _setmode(fileno(stdout), _O_BINARY);
963 _setmode(fileno(stderr), _O_BINARY);
964 if (!QueryPerformanceFrequency((LARGE_INTEGER*)&windows_perf_freq)) {
965 return ErrorSystemResources;
966 }
967#elif defined(__MACH__)
968 host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &macos_monotonic_clock);
969 host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &macos_calendar_clock);
970#endif
971 return 0;
972}
973
974#define VT_RED "\x1b[31;1m"
975#define VT_GREEN "\x1b[32;1m"
976#define VT_CYAN "\x1b[36;1m"
977#define VT_WHITE "\x1b[37;1m"
978#define VT_BOLD "\x1b[0;1m"
979#define VT_RESET "\x1b[0m"
980
981static void set_color_posix(TermColor color) {
982 switch (color) {
983 case TermColorRed:
984 fprintf(stderr, VT_RED);
985 break;
986 case TermColorGreen:
987 fprintf(stderr, VT_GREEN);
988 break;
989 case TermColorCyan:
990 fprintf(stderr, VT_CYAN);
991 break;
992 case TermColorWhite:
993 fprintf(stderr, VT_WHITE);
994 break;
995 case TermColorBold:
996 fprintf(stderr, VT_BOLD);
997 break;
998 case TermColorReset:
999 fprintf(stderr, VT_RESET);
1000 break;
1001 }
1002}
1003
1004
1005#if defined(ZIG_OS_WINDOWS)
1006bool got_orig_console_attrs = false;
1007WORD original_console_attributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE;
1008#endif
1009
1010void os_stderr_set_color(TermColor color) {
1011#if defined(ZIG_OS_WINDOWS)
1012 if (is_stderr_cyg_pty()) {
1013 set_color_posix(color);
1014 return;
1015 }
1016 HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
1017 if (stderr_handle == INVALID_HANDLE_VALUE)
1018 zig_panic("unable to get stderr handle");
1019 fflush(stderr);
1020
1021 if (!got_orig_console_attrs) {
1022 got_orig_console_attrs = true;
1023 CONSOLE_SCREEN_BUFFER_INFO info;
1024 if (GetConsoleScreenBufferInfo(stderr_handle, &info)) {
1025 original_console_attributes = info.wAttributes;
1026 }
1027 }
1028
1029 switch (color) {
1030 case TermColorRed:
1031 SetConsoleTextAttribute(stderr_handle, FOREGROUND_RED|FOREGROUND_INTENSITY);
1032 break;
1033 case TermColorGreen:
1034 SetConsoleTextAttribute(stderr_handle, FOREGROUND_GREEN|FOREGROUND_INTENSITY);
1035 break;
1036 case TermColorCyan:
1037 SetConsoleTextAttribute(stderr_handle, FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY);
1038 break;
1039 case TermColorWhite:
1040 case TermColorBold:
1041 SetConsoleTextAttribute(stderr_handle,
1042 FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY);
1043 break;
1044 case TermColorReset:
1045 SetConsoleTextAttribute(stderr_handle, original_console_attributes);
1046 break;
1047 }
1048#else
1049 set_color_posix(color);
1050#endif
1051}
1052
1053#if defined(ZIG_OS_WINDOWS)
1054// Ported from std/unicode.zig
1055struct Utf16LeIterator {
1056 uint8_t *bytes;
1057 size_t i;
1058};
1059
1060// Ported from std/unicode.zig
1061static Utf16LeIterator Utf16LeIterator_init(WCHAR *ptr) {
1062 return {(uint8_t*)ptr, 0};
1063}
1064
1065// Ported from std/unicode.zig
1066static Optional<uint32_t> Utf16LeIterator_nextCodepoint(Utf16LeIterator *it) {
1067 if (it->bytes[it->i] == 0 && it->bytes[it->i + 1] == 0)
1068 return {};
1069 uint32_t c0 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8);
1070 if ((c0 & ~((uint32_t)0x03ff)) == 0xd800) {
1071 // surrogate pair
1072 it->i += 2;
1073 assert(it->bytes[it->i] != 0 || it->bytes[it->i + 1] != 0);
1074 uint32_t c1 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8);
1075 assert((c1 & ~((uint32_t)0x03ff)) == 0xdc00);
1076 it->i += 2;
1077 return Optional<uint32_t>::some(0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff)));
1078 } else {
1079 assert((c0 & ~((uint32_t)0x03ff)) != 0xdc00);
1080 it->i += 2;
1081 return Optional<uint32_t>::some(c0);
1082 }
1083}
1084
1085// Ported from std/unicode.zig
1086static uint8_t utf8CodepointSequenceLength(uint32_t c) {
1087 if (c < 0x80) return 1;
1088 if (c < 0x800) return 2;
1089 if (c < 0x10000) return 3;
1090 if (c < 0x110000) return 4;
1091 zig_unreachable();
1092}
1093
1094// Ported from std.unicode.utf8ByteSequenceLength
1095static uint8_t utf8ByteSequenceLength(uint8_t first_byte) {
1096 if (first_byte < 0b10000000) return 1;
1097 if ((first_byte & 0b11100000) == 0b11000000) return 2;
1098 if ((first_byte & 0b11110000) == 0b11100000) return 3;
1099 if ((first_byte & 0b11111000) == 0b11110000) return 4;
1100 zig_unreachable();
1101}
1102
1103// Ported from std/unicode.zig
1104static size_t utf8Encode(uint32_t c, Slice<uint8_t> out) {
1105 size_t length = utf8CodepointSequenceLength(c);
1106 assert(out.len >= length);
1107 switch (length) {
1108 // The pattern for each is the same
1109 // - Increasing the initial shift by 6 each time
1110 // - Each time after the first shorten the shifted
1111 // value to a max of 0b111111 (63)
1112 case 1:
1113 out.ptr[0] = c; // Can just do 0 + codepoint for initial range
1114 break;
1115 case 2:
1116 out.ptr[0] = 0b11000000 | (c >> 6);
1117 out.ptr[1] = 0b10000000 | (c & 0b111111);
1118 break;
1119 case 3:
1120 assert(!(0xd800 <= c && c <= 0xdfff));
1121 out.ptr[0] = 0b11100000 | (c >> 12);
1122 out.ptr[1] = 0b10000000 | ((c >> 6) & 0b111111);
1123 out.ptr[2] = 0b10000000 | (c & 0b111111);
1124 break;
1125 case 4:
1126 out.ptr[0] = 0b11110000 | (c >> 18);
1127 out.ptr[1] = 0b10000000 | ((c >> 12) & 0b111111);
1128 out.ptr[2] = 0b10000000 | ((c >> 6) & 0b111111);
1129 out.ptr[3] = 0b10000000 | (c & 0b111111);
1130 break;
1131 default:
1132 zig_unreachable();
1133 }
1134 return length;
1135}
1136
1137// Ported from std.unicode.utf8Decode2
1138static uint32_t utf8Decode2(Slice<uint8_t> bytes) {
1139 assert(bytes.len == 2);
1140 assert((bytes.at(0) & 0b11100000) == 0b11000000);
1141
1142 uint32_t value = bytes.at(0) & 0b00011111;
1143 assert((bytes.at(1) & 0b11000000) == 0b10000000);
1144 value <<= 6;
1145 value |= bytes.at(1) & 0b00111111;
1146
1147 assert(value >= 0x80);
1148 return value;
1149}
1150
1151// Ported from std.unicode.utf8Decode3
1152static uint32_t utf8Decode3(Slice<uint8_t> bytes) {
1153 assert(bytes.len == 3);
1154 assert((bytes.at(0) & 0b11110000) == 0b11100000);
1155
1156 uint32_t value = bytes.at(0) & 0b00001111;
1157 assert((bytes.at(1) & 0b11000000) == 0b10000000);
1158 value <<= 6;
1159 value |= bytes.at(1) & 0b00111111;
1160
1161 assert((bytes.at(2) & 0b11000000) == 0b10000000);
1162 value <<= 6;
1163 value |= bytes.at(2) & 0b00111111;
1164
1165 assert(value >= 0x80);
1166 assert(value < 0xd800 || value > 0xdfff);
1167 return value;
1168}
1169
1170// Ported from std.unicode.utf8Decode4
1171static uint32_t utf8Decode4(Slice<uint8_t> bytes) {
1172 assert(bytes.len == 4);
1173 assert((bytes.at(0) & 0b11111000) == 0b11110000);
1174
1175 uint32_t value = bytes.at(0) & 0b00000111;
1176 assert((bytes.at(1) & 0b11000000) == 0b10000000);
1177 value <<= 6;
1178 value |= bytes.at(1) & 0b00111111;
1179
1180 assert((bytes.at(2) & 0b11000000) == 0b10000000);
1181 value <<= 6;
1182 value |= bytes.at(2) & 0b00111111;
1183
1184 assert((bytes.at(3) & 0b11000000) == 0b10000000);
1185 value <<= 6;
1186 value |= bytes.at(3) & 0b00111111;
1187
1188 assert(value >= 0x10000 && value <= 0x10FFFF);
1189 return value;
1190}
1191
1192// Ported from std.unicode.utf8Decode
1193static uint32_t utf8Decode(Slice<uint8_t> bytes) {
1194 switch (bytes.len) {
1195 case 1:
1196 return bytes.at(0);
1197 break;
1198 case 2:
1199 return utf8Decode2(bytes);
1200 break;
1201 case 3:
1202 return utf8Decode3(bytes);
1203 break;
1204 case 4:
1205 return utf8Decode4(bytes);
1206 break;
1207 default:
1208 zig_unreachable();
1209 }
1210}
1211// Ported from std.unicode.utf16leToUtf8Alloc
1212static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) {
1213 // optimistically guess that it will all be ascii.
1214 buf_resize(out, 0);
1215 size_t out_index = 0;
1216 Utf16LeIterator it = Utf16LeIterator_init(utf16le);
1217 for (;;) {
1218 Optional<uint32_t> opt_codepoint = Utf16LeIterator_nextCodepoint(&it);
1219 if (!opt_codepoint.is_some) break;
1220 uint32_t codepoint = opt_codepoint.value;
1221
1222 size_t utf8_len = utf8CodepointSequenceLength(codepoint);
1223 buf_resize(out, buf_len(out) + utf8_len);
1224 utf8Encode(codepoint, {(uint8_t*)buf_ptr(out)+out_index, buf_len(out)-out_index});
1225 out_index += utf8_len;
1226 }
1227}
1228
1229// Ported from std.unicode.utf8ToUtf16Le
1230static size_t utf8_to_utf16le(WCHAR *utf16_le, Slice<uint8_t> utf8) {
1231 size_t dest_i = 0;
1232 size_t src_i = 0;
1233 while (src_i < utf8.len) {
1234 uint8_t n = utf8ByteSequenceLength(utf8.at(src_i));
1235 size_t next_src_i = src_i + n;
1236 uint32_t codepoint = utf8Decode(utf8.slice(src_i, next_src_i));
1237 if (codepoint < 0x10000) {
1238 utf16_le[dest_i] = codepoint;
1239 dest_i += 1;
1240 } else {
1241 WCHAR high = ((codepoint - 0x10000) >> 10) + 0xD800;
1242 WCHAR low = (codepoint & 0x3FF) + 0xDC00;
1243 utf16_le[dest_i] = high;
1244 utf16_le[dest_i + 1] = low;
1245 dest_i += 2;
1246 }
1247 src_i = next_src_i;
1248 }
1249 return dest_i;
1250}
1251
1252// Ported from std.os.windows.sliceToPrefixedFileW
1253PathSpace slice_to_prefixed_file_w(Slice<uint8_t> path) {
1254 PathSpace path_space;
1255 for (size_t idx = 0; idx < path.len; idx++) {
1256 assert(path.ptr[idx] != '*' && path.ptr[idx] != '?' && path.ptr[idx] != '"' &&
1257 path.ptr[idx] != '<' && path.ptr[idx] != '>' && path.ptr[idx] != '|');
1258 }
1259
1260 size_t start_index;
1261 if (memStartsWith(path, str("\\?")) || !isAbsoluteWindows(path)) {
1262 start_index = 0;
1263 } else {
1264 static WCHAR prefix[4] = { u'\\', u'?', u'?', u'\\' };
1265 memCopy(path_space.data.slice(), Slice<WCHAR> { prefix, 4 });
1266 start_index = 4;
1267 }
1268
1269 path_space.len = start_index + utf8_to_utf16le(path_space.data.slice().sliceFrom(start_index).ptr, path);
1270 assert(path_space.len <= path_space.data.len);
1271
1272 Slice<WCHAR> path_slice = path_space.data.slice().slice(0, path_space.len);
1273 for (size_t elem_idx = 0; elem_idx < path_slice.len; elem_idx += 1) {
1274 if (path_slice.at(elem_idx) == '/') {
1275 path_slice.at(elem_idx) = '\\';
1276 }
1277 }
1278
1279 path_space.data.items[path_space.len] = 0;
1280 return path_space;
1281}
1282#endif
src/stage1/os.hpp deleted-120
...@@ -1,120 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_OS_HPP
9#define ZIG_OS_HPP
10
11#include "list.hpp"
12#include "buffer.hpp"
13#include "error.hpp"
14#include "zig_llvm.h"
15#include "windows_sdk.h"
16
17#include <stdio.h>
18#include <inttypes.h>
19
20#if defined(__APPLE__)
21#define ZIG_OS_DARWIN
22#elif defined(_WIN32)
23#define ZIG_OS_WINDOWS
24#elif defined(__linux__)
25#define ZIG_OS_LINUX
26#elif defined(__FreeBSD__)
27#define ZIG_OS_FREEBSD
28#elif defined(__NetBSD__)
29#define ZIG_OS_NETBSD
30#elif defined(__DragonFly__)
31#define ZIG_OS_DRAGONFLY
32#elif defined(__OpenBSD__)
33#define ZIG_OS_OPENBSD
34#elif defined(__HAIKU__)
35#define ZIG_OS_HAIKU
36#elif defined(__sun)
37#define ZIG_OS_SOLARIS
38#else
39#define ZIG_OS_UNKNOWN
40#endif
41
42#if defined(__x86_64__)
43#define ZIG_ARCH_X86_64
44#elif defined(__aarch64__)
45#define ZIG_ARCH_ARM64
46#elif defined(__ARM_EABI__)
47#define ZIG_ARCH_ARM
48#else
49#define ZIG_ARCH_UNKNOWN
50#endif
51
52#if defined(ZIG_OS_WINDOWS)
53#define ZIG_PRI_usize "Iu"
54#define ZIG_PRI_i64 "I64d"
55#define ZIG_PRI_u64 "I64u"
56#define ZIG_PRI_llu "I64u"
57#define ZIG_PRI_x64 "I64x"
58#define OS_SEP "\\"
59#define ZIG_OS_SEP_CHAR '\\'
60#else
61#define ZIG_PRI_usize "zu"
62#define ZIG_PRI_i64 PRId64
63#define ZIG_PRI_u64 PRIu64
64#define ZIG_PRI_llu "llu"
65#define ZIG_PRI_x64 PRIx64
66#define OS_SEP "/"
67#define ZIG_OS_SEP_CHAR '/'
68#endif
69
70enum TermColor {
71 TermColorRed,
72 TermColorGreen,
73 TermColorCyan,
74 TermColorWhite,
75 TermColorBold,
76 TermColorReset,
77};
78
79struct OsTimeStamp {
80 int64_t sec;
81 int64_t nsec;
82};
83
84int os_init(void);
85
86void os_path_dirname(Buf *full_path, Buf *out_dirname);
87void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
88void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname);
89void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);
90Buf os_path_resolve(Buf **paths_ptr, size_t paths_len);
91bool os_path_is_absolute(Buf *path);
92
93Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);
94Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);
95
96Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);
97Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);
98
99Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents);
100Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents);
101
102Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);
103
104bool os_stderr_supports_color(void);
105void os_stderr_set_color(TermColor color);
106
107Error os_rename(Buf *src_path, Buf *dest_path);
108OsTimeStamp os_timestamp_monotonic(void);
109
110bool os_is_sep(uint8_t c);
111
112const size_t PATH_MAX_WIDE = 32767;
113
114struct PathSpace {
115 Array<wchar_t, PATH_MAX_WIDE> data;
116 size_t len;
117};
118
119PathSpace slice_to_prefixed_file_w(Slice<uint8_t> path);
120#endif
src/stage1/parse_f128.c deleted-1085
...@@ -1,1085 +0,0 @@
1// Code ported from musl libc 8f12c4e110acb3bbbdc8abfb3a552c3ced718039
2// and then modified to use softfloat and to assume f128 for everything
3
4#include "parse_f128.h"
5#include "softfloat.h"
6#include "zigendian.h"
7#include <stddef.h>
8#include <sys/types.h>
9#include <errno.h>
10#include <limits.h>
11#include <string.h>
12#include <math.h>
13
14#define shcnt(f) ((f)->shcnt + ((f)->rpos - (f)->buf))
15#define shlim(f, lim) __shlim((f), (lim))
16#define shgetc(f) (((f)->rpos != (f)->shend) ? *(f)->rpos++ : __shgetc(f))
17#define shunget(f) ((f)->shlim>=0 ? (void)(f)->rpos-- : (void)0)
18
19#define sh_fromstring(f, s) \
20 ((f)->buf = (f)->rpos = (void *)(s), (f)->rend = (void*)-1)
21
22#define LD_B1B_DIG 4
23#define LD_B1B_MAX 10384593, 717069655, 257060992, 658440191
24#define KMAX 2048
25
26#define MASK (KMAX-1)
27
28#define CONCAT2(x,y) x ## y
29#define CONCAT(x,y) CONCAT2(x,y)
30
31#define F_PERM 1
32#define F_NORD 4
33#define F_NOWR 8
34#define F_EOF 16
35#define F_ERR 32
36#define F_SVB 64
37#define F_APP 128
38
39#define EOF (-1)
40
41#define LDBL_MANT_DIG 113
42#define LDBL_MIN_EXP (-16381)
43#define LDBL_MAX_EXP 16384
44
45#define LDBL_DIG 33
46#define LDBL_MIN_10_EXP (-4931)
47#define LDBL_MAX_10_EXP 4932
48
49#define DECIMAL_DIG 36
50
51#if defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
52union ldshape {
53 float128_t f;
54 struct {
55 uint64_t lo;
56 uint32_t mid;
57 uint16_t top;
58 uint16_t se;
59 } i;
60 struct {
61 uint64_t lo;
62 uint64_t hi;
63 } i2;
64};
65#elif defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN
66union ldshape {
67 float128_t f;
68 struct {
69 uint16_t se;
70 uint16_t top;
71 uint32_t mid;
72 uint64_t lo;
73 } i;
74 struct {
75 uint64_t hi;
76 uint64_t lo;
77 } i2;
78};
79#else
80#error Unsupported endian
81#endif
82
83struct MuslFILE {
84 unsigned flags;
85 unsigned char *rpos, *rend;
86 int (*close)(struct MuslFILE *);
87 unsigned char *wend, *wpos;
88 unsigned char *mustbezero_1;
89 unsigned char *wbase;
90 size_t (*read)(struct MuslFILE *, unsigned char *, size_t);
91 size_t (*write)(struct MuslFILE *, const unsigned char *, size_t);
92 off_t (*seek)(struct MuslFILE *, off_t, int);
93 unsigned char *buf;
94 size_t buf_size;
95 struct MuslFILE *prev, *next;
96 int fd;
97 int pipe_pid;
98 long lockcount;
99 int mode;
100 volatile int lock;
101 int lbf;
102 void *cookie;
103 off_t off;
104 char *getln_buf;
105 void *mustbezero_2;
106 unsigned char *shend;
107 off_t shlim, shcnt;
108 struct MuslFILE *prev_locked, *next_locked;
109 struct __locale_struct *locale;
110};
111
112static void __shlim(struct MuslFILE *f, off_t lim)
113{
114 f->shlim = lim;
115 f->shcnt = f->buf - f->rpos;
116 /* If lim is nonzero, rend must be a valid pointer. */
117 if (lim && f->rend - f->rpos > lim)
118 f->shend = f->rpos + lim;
119 else
120 f->shend = f->rend;
121}
122
123static int __toread(struct MuslFILE *f)
124{
125 f->mode |= f->mode-1;
126 if (f->wpos != f->wbase) f->write(f, 0, 0);
127 f->wpos = f->wbase = f->wend = 0;
128 if (f->flags & F_NORD) {
129 f->flags |= F_ERR;
130 return EOF;
131 }
132 f->rpos = f->rend = f->buf + f->buf_size;
133 return (f->flags & F_EOF) ? EOF : 0;
134}
135
136static int __uflow(struct MuslFILE *f)
137{
138 unsigned char c;
139 if (!__toread(f) && f->read(f, &c, 1)==1) return c;
140 return EOF;
141}
142
143static int __shgetc(struct MuslFILE *f)
144{
145 int c;
146 off_t cnt = shcnt(f);
147 if ((f->shlim && cnt >= f->shlim) || (c=__uflow(f)) < 0) {
148 f->shcnt = f->buf - f->rpos + cnt;
149 f->shend = f->rpos;
150 f->shlim = -1;
151 return EOF;
152 }
153 cnt++;
154 if (f->shlim && f->rend - f->rpos > f->shlim - cnt)
155 f->shend = f->rpos + (f->shlim - cnt);
156 else
157 f->shend = f->rend;
158 f->shcnt = f->buf - f->rpos + cnt;
159 if (f->rpos[-1] != c) f->rpos[-1] = c;
160 return c;
161}
162
163static long long scanexp(struct MuslFILE *f, int pok)
164{
165 int c;
166 int x;
167 long long y;
168 int neg = 0;
169
170 c = shgetc(f);
171 if (c=='+' || c=='-') {
172 neg = (c=='-');
173 c = shgetc(f);
174 if (c-'0'>=10U && pok) shunget(f);
175 }
176 if (c-'0'>=10U && c!='_') {
177 shunget(f);
178 return LLONG_MIN;
179 }
180 for (x=0; ; c = shgetc(f)) {
181 if (c=='_') {
182 continue;
183 } else if (c-'0'<10U && x<INT_MAX/10) {
184 x = 10*x + c-'0';
185 } else {
186 break;
187 }
188 }
189 for (y=x; ; c = shgetc(f)) {
190 if (c=='_') {
191 continue;
192 } else if (c-'0'<10U && y<LLONG_MAX/100) {
193 y = 10*y + c-'0';
194 } else {
195 break;
196 }
197 }
198 for (; c-'0'<10U || c=='_'; c = shgetc(f));
199 shunget(f);
200 return neg ? -y : y;
201}
202
203static float128_t copysignf128(float128_t x, float128_t y)
204{
205 union ldshape ux = {x}, uy = {y};
206 ux.i.se &= 0x7fff;
207 ux.i.se |= uy.i.se & 0x8000;
208 return ux.f;
209}
210
211static void mul_eq_f128_float(float128_t *x, float op_float) {
212 //x *= 0x1p120f;
213 float32_t op_f32;
214 memcpy(&op_f32, &op_float, sizeof(float));
215 float128_t op_f128;
216 f32_to_f128M(op_f32, &op_f128);
217 float128_t new_value;
218 f128M_mul(x, &op_f128, &new_value);
219 *x = new_value;
220}
221
222static float128_t dbl_to_f128(double x) {
223 float64_t x_f64;
224 memcpy(&x_f64, &x, sizeof(double));
225 float128_t result;
226 f64_to_f128M(x_f64, &result);
227 return result;
228}
229
230static float128_t fmodf128(float128_t x, float128_t y)
231{
232 union ldshape ux = {x}, uy = {y};
233 int ex = ux.i.se & 0x7fff;
234 int ey = uy.i.se & 0x7fff;
235 int sx = ux.i.se & 0x8000;
236
237 float128_t zero;
238 ui32_to_f128M(0, &zero);
239 // if (y == 0 || isnan(y) || ex == 0x7fff)
240 if (f128M_eq(&y, &zero) || f128M_isSignalingNaN(&y) || ex == 0x7fff) {
241 //return (x*y)/(x*y);
242 float128_t x_times_y;
243 f128M_mul(&x, &y, &x_times_y);
244 float128_t result;
245 f128M_div(&x_times_y, &x_times_y, &result);
246 return result;
247 }
248 ux.i.se = ex;
249 uy.i.se = ey;
250 //if (ux.f <= uy.f) {
251 if (f128M_le(&ux.f, &uy.f)) {
252 //if (ux.f == uy.f) {
253 if (f128M_eq(&ux.f, &uy.f)) {
254 //return 0*x;
255 float128_t result;
256 f128M_mul(&zero, &x, &result);
257 return result;
258 }
259 return x;
260 }
261
262 /* normalize x and y */
263 if (!ex) {
264 //ux.f *= 0x1p120f;
265 mul_eq_f128_float(&ux.f, 0x1p120f);
266
267 ex = ux.i.se - 120;
268 }
269 if (!ey) {
270 //uy.f *= 0x1p120f;
271 mul_eq_f128_float(&uy.f, 0x1p120f);
272
273 ey = uy.i.se - 120;
274 }
275
276 /* x mod y */
277 uint64_t hi, lo, xhi, xlo, yhi, ylo;
278 xhi = (ux.i2.hi & -1ULL>>16) | 1ULL<<48;
279 yhi = (uy.i2.hi & -1ULL>>16) | 1ULL<<48;
280 xlo = ux.i2.lo;
281 ylo = uy.i2.lo;
282 for (; ex > ey; ex--) {
283 hi = xhi - yhi;
284 lo = xlo - ylo;
285 if (xlo < ylo)
286 hi -= 1;
287 if (hi >> 63 == 0) {
288 if ((hi|lo) == 0) {
289 //return 0*x;
290 float128_t result;
291 f128M_mul(&zero, &x, &result);
292 return result;
293 }
294 xhi = 2*hi + (lo>>63);
295 xlo = 2*lo;
296 } else {
297 xhi = 2*xhi + (xlo>>63);
298 xlo = 2*xlo;
299 }
300 }
301 hi = xhi - yhi;
302 lo = xlo - ylo;
303 if (xlo < ylo)
304 hi -= 1;
305 if (hi >> 63 == 0) {
306 if ((hi|lo) == 0) {
307 //return 0*x;
308 float128_t result;
309 f128M_mul(&zero, &x, &result);
310 return result;
311 }
312 xhi = hi;
313 xlo = lo;
314 }
315 for (; xhi >> 48 == 0; xhi = 2*xhi + (xlo>>63), xlo = 2*xlo, ex--);
316 ux.i2.hi = xhi;
317 ux.i2.lo = xlo;
318
319 /* scale result */
320 if (ex <= 0) {
321 ux.i.se = (ex+120)|sx;
322 //ux.f *= 0x1p-120f;
323 mul_eq_f128_float(&ux.f, 0x1p-120f);
324 } else
325 ux.i.se = ex|sx;
326 return ux.f;
327}
328
329static float128_t int_mul_f128_cast_u32(int sign, uint32_t x0) {
330 float128_t x0_f128;
331 ui32_to_f128M(x0, &x0_f128);
332 float128_t sign_f128;
333 i32_to_f128M(sign, &sign_f128);
334 float128_t result;
335 f128M_mul(&sign_f128, &x0_f128, &result);
336 return result;
337}
338
339static float128_t triple_divide(int sign, uint32_t x0, int p10s) {
340 float128_t part1 = int_mul_f128_cast_u32(sign, x0);
341 float128_t p10s_f128;
342 i32_to_f128M(p10s, &p10s_f128);
343 float128_t result;
344 f128M_div(&part1, &p10s_f128, &result);
345 return result;
346}
347
348static float128_t triple_multiply(int sign, uint32_t x0, int p10s) {
349 float128_t part1 = int_mul_f128_cast_u32(sign, x0);
350 float128_t p10s_f128;
351 i32_to_f128M(p10s, &p10s_f128);
352 float128_t result;
353 f128M_mul(&part1, &p10s_f128, &result);
354 return result;
355}
356
357static void mul_eq_f128_int(float128_t *y, int sign) {
358 float128_t sign_f128;
359 i32_to_f128M(sign, &sign_f128);
360 float128_t new_value;
361 f128M_mul(y, &sign_f128, &new_value);
362 *y = new_value;
363}
364
365static float128_t make_f128(uint64_t hi, uint64_t lo) {
366 union ldshape ux;
367 ux.i2.hi = hi;
368 ux.i2.lo = lo;
369 return ux.f;
370}
371
372static void mul_eq_f128_f128(float128_t *a, float128_t b) {
373 float128_t new_value;
374 f128M_mul(a, &b, &new_value);
375 *a = new_value;
376}
377
378static void add_eq_f128_dbl(float128_t *a, double b) {
379 float64_t b_f64;
380 memcpy(&b_f64, &b, sizeof(double));
381
382 float128_t b_f128;
383 f64_to_f128M(b_f64, &b_f128);
384
385 float128_t new_value;
386 f128M_add(a, &b_f128, &new_value);
387 *a = new_value;
388}
389
390static float128_t scalbnf128(float128_t x, int n)
391{
392 union ldshape u;
393
394 if (n > 16383) {
395 //x *= 0x1p16383q;
396 mul_eq_f128_f128(&x, make_f128(0x7ffe000000000000, 0x0000000000000000));
397 n -= 16383;
398 if (n > 16383) {
399 //x *= 0x1p16383q;
400 mul_eq_f128_f128(&x, make_f128(0x7ffe000000000000, 0x0000000000000000));
401 n -= 16383;
402 if (n > 16383)
403 n = 16383;
404 }
405 } else if (n < -16382) {
406 //x *= 0x1p-16382q * 0x1p113q;
407 {
408 float128_t mul_result;
409 float128_t a = make_f128(0x0001000000000000, 0x0000000000000000);
410 float128_t b = make_f128(0x4070000000000000, 0x0000000000000000);
411 f128M_mul(&a, &b, &mul_result);
412 mul_eq_f128_f128(&x, mul_result);
413 }
414 n += 16382 - 113;
415 if (n < -16382) {
416 //x *= 0x1p-16382q * 0x1p113q;
417 {
418 float128_t mul_result;
419 float128_t a = make_f128(0x0001000000000000, 0x0000000000000000);
420 float128_t b = make_f128(0x4070000000000000, 0x0000000000000000);
421 f128M_mul(&a, &b, &mul_result);
422 mul_eq_f128_f128(&x, mul_result);
423 }
424 n += 16382 - 113;
425 if (n < -16382)
426 n = -16382;
427 }
428 }
429 //u.f = 1.0;
430 ui32_to_f128M(1, &u.f);
431 u.i.se = 0x3fff + n;
432 mul_eq_f128_f128(&x, u.f);
433 return x;
434}
435
436static float128_t fabsf128(float128_t x)
437{
438 union ldshape u = {x};
439
440 u.i.se &= 0x7fff;
441 return u.f;
442}
443
444static float128_t decfloat(struct MuslFILE *f, int c, int bits, int emin, int sign, int pok)
445{
446 uint32_t x[KMAX];
447 static const uint32_t th[] = { LD_B1B_MAX };
448 int i, j, k, a, z;
449 long long lrp=0, dc=0;
450 long long e10=0;
451 int lnz = 0;
452 int gotdig = 0, gotrad = 0;
453 int rp;
454 int e2;
455 int emax = -emin-bits+3;
456 int denormal = 0;
457 float128_t y;
458 float128_t zero;
459 ui32_to_f128M(0, &zero);
460 float128_t frac=zero;
461 float128_t bias=zero;
462 static const int p10s[] = { 10, 100, 1000, 10000,
463 100000, 1000000, 10000000, 100000000 };
464
465 j=0;
466 k=0;
467
468 /* Don't let leading zeros/underscores consume buffer space */
469 for (; ; c = shgetc(f)) {
470 if (c=='_') {
471 continue;
472 } else if (c=='0') {
473 gotdig=1;
474 } else {
475 break;
476 }
477 }
478
479 if (c=='.') {
480 gotrad = 1;
481 for (c = shgetc(f); ; c = shgetc(f)) {
482 if (c == '_') {
483 continue;
484 } else if (c=='0') {
485 gotdig=1;
486 lrp--;
487 } else {
488 break;
489 }
490 }
491 }
492
493 x[0] = 0;
494 for (; c-'0'<10U || c=='.' || c=='_'; c = shgetc(f)) {
495 if (c == '_') {
496 continue;
497 } else if (c == '.') {
498 if (gotrad) break;
499 gotrad = 1;
500 lrp = dc;
501 } else if (k < KMAX-3) {
502 dc++;
503 if (c!='0') lnz = dc;
504 if (j) x[k] = x[k]*10 + c-'0';
505 else x[k] = c-'0';
506 if (++j==9) {
507 k++;
508 j=0;
509 }
510 gotdig=1;
511 } else {
512 dc++;
513 if (c!='0') {
514 lnz = (KMAX-4)*9;
515 x[KMAX-4] |= 1;
516 }
517 }
518 }
519 if (!gotrad) lrp=dc;
520
521 if (gotdig && (c|32)=='e') {
522 e10 = scanexp(f, pok);
523 if (e10 == LLONG_MIN) {
524 if (pok) {
525 shunget(f);
526 } else {
527 shlim(f, 0);
528 return zero;
529 }
530 e10 = 0;
531 }
532 lrp += e10;
533 } else if (c>=0) {
534 shunget(f);
535 }
536 if (!gotdig) {
537 errno = EINVAL;
538 shlim(f, 0);
539 return zero;
540 }
541
542 /* Handle zero specially to avoid nasty special cases later */
543 if (!x[0]) {
544 //return sign * 0.0;
545 return dbl_to_f128(sign * 0.0);
546 }
547
548 /* Optimize small integers (w/no exponent) and over/under-flow */
549 if (lrp==dc && dc<10 && (bits>30 || x[0]>>bits==0)) {
550 //return sign * (float128_t)x[0];
551 float128_t sign_f128;
552 i32_to_f128M(sign, &sign_f128);
553 float128_t x0_f128;
554 ui32_to_f128M(x[0], &x0_f128);
555 float128_t result;
556 f128M_mul(&sign_f128, &x0_f128, &result);
557 return result;
558 }
559 if (lrp > -emin/2) {
560 errno = ERANGE;
561 //return sign * LDBL_MAX * LDBL_MAX;
562 return zero;
563 }
564 if (lrp < emin-2*LDBL_MANT_DIG) {
565 errno = ERANGE;
566 //return sign * LDBL_MIN * LDBL_MIN;
567 return zero;
568 }
569
570 /* Align incomplete final B1B digit */
571 if (j) {
572 for (; j<9; j++) x[k]*=10;
573 k++;
574 j=0;
575 }
576
577 a = 0;
578 z = k;
579 e2 = 0;
580 rp = lrp;
581
582 /* Optimize small to mid-size integers (even in exp. notation) */
583 if (lnz<9 && lnz<=rp && rp < 18) {
584 if (rp == 9) {
585 //return sign * (float128_t)(x[0]);
586 return int_mul_f128_cast_u32(sign, x[0]);
587 }
588 if (rp < 9) {
589 //return sign * (float128_t)(x[0]) / p10s[8-rp];
590 return triple_divide(sign, x[0], p10s[8-rp]);
591 }
592 int bitlim = bits-3*(int)(rp-9);
593 if (bitlim>30 || x[0]>>bitlim==0)
594 //return sign * (float128_t)(x[0]) * p10s[rp-10];
595 return triple_multiply(sign, x[0], p10s[rp-10]);
596 }
597
598 /* Drop trailing zeros */
599 for (; !x[z-1]; z--);
600
601 /* Align radix point to B1B digit boundary */
602 if (rp % 9) {
603 int rpm9 = rp>=0 ? rp%9 : rp%9+9;
604 int p10 = p10s[8-rpm9];
605 uint32_t carry = 0;
606 for (k=a; k!=z; k++) {
607 uint32_t tmp = x[k] % p10;
608 x[k] = x[k]/p10 + carry;
609 carry = 1000000000/p10 * tmp;
610 if (k==a && !x[k]) {
611 a = (a+1 & MASK);
612 rp -= 9;
613 }
614 }
615 if (carry) x[z++] = carry;
616 rp += 9-rpm9;
617 }
618
619 /* Upscale until desired number of bits are left of radix point */
620 while (rp < 9*LD_B1B_DIG || (rp == 9*LD_B1B_DIG && x[a]<th[0])) {
621 uint32_t carry = 0;
622 e2 -= 29;
623 for (k=(z-1 & MASK); ; k=(k-1 & MASK)) {
624 uint64_t tmp = ((uint64_t)x[k] << 29) + carry;
625 if (tmp > 1000000000) {
626 carry = tmp / 1000000000;
627 x[k] = tmp % 1000000000;
628 } else {
629 carry = 0;
630 x[k] = tmp;
631 }
632 if (k==(z-1 & MASK) && k!=a && !x[k]) z = k;
633 if (k==a) break;
634 }
635 if (carry) {
636 rp += 9;
637 a = (a-1 & MASK);
638 if (a == z) {
639 z = (z-1 & MASK);
640 x[z-1 & MASK] |= x[z];
641 }
642 x[a] = carry;
643 }
644 }
645
646 /* Downscale until exactly number of bits are left of radix point */
647 for (;;) {
648 uint32_t carry = 0;
649 int sh = 1;
650 for (i=0; i<LD_B1B_DIG; i++) {
651 k = (a+i & MASK);
652 if (k == z || x[k] < th[i]) {
653 i=LD_B1B_DIG;
654 break;
655 }
656 if (x[a+i & MASK] > th[i]) break;
657 }
658 if (i==LD_B1B_DIG && rp==9*LD_B1B_DIG) break;
659 /* FIXME: find a way to compute optimal sh */
660 if (rp > 9+9*LD_B1B_DIG) sh = 9;
661 e2 += sh;
662 for (k=a; k!=z; k=(k+1 & MASK)) {
663 uint32_t tmp = x[k] & (1<<sh)-1;
664 x[k] = (x[k]>>sh) + carry;
665 carry = (1000000000>>sh) * tmp;
666 if (k==a && !x[k]) {
667 a = (a+1 & MASK);
668 i--;
669 rp -= 9;
670 }
671 }
672 if (carry) {
673 if ((z+1 & MASK) != a) {
674 x[z] = carry;
675 z = (z+1 & MASK);
676 } else x[z-1 & MASK] |= 1;
677 }
678 }
679
680 /* Assemble desired bits into floating point variable */
681 for (y=zero,i=0; i<LD_B1B_DIG; i++) {
682 if ((a+i & MASK)==z) x[(z=(z+1 & MASK))-1] = 0;
683 //y = 1000000000.0L * y + x[a+i & MASK];
684 float128_t const_f128;
685 ui64_to_f128M(1000000000, &const_f128);
686 float128_t mul_y;
687 f128M_mul(&const_f128, &y, &mul_y);
688 float128_t x_f128;
689 ui32_to_f128M(x[a+i & MASK], &x_f128);
690 f128M_add(&mul_y, &x_f128, &y);
691 }
692
693 //y *= sign;
694 mul_eq_f128_int(&y, sign);
695
696 /* Limit precision for denormal results */
697 if (bits > LDBL_MANT_DIG+e2-emin) {
698 bits = LDBL_MANT_DIG+e2-emin;
699 if (bits<0) bits=0;
700 denormal = 1;
701 }
702
703 /* Calculate bias term to force rounding, move out lower bits */
704 if (bits < LDBL_MANT_DIG) {
705 bias = copysignf128(dbl_to_f128(scalbn(1, 2*LDBL_MANT_DIG-bits-1)), y);
706 frac = fmodf128(y, dbl_to_f128(scalbn(1, LDBL_MANT_DIG-bits)));
707 //y -= frac;
708 {
709 float128_t new_value;
710 f128M_sub(&y, &frac, &new_value);
711 y = new_value;
712 }
713 //y += bias;
714 {
715 float128_t new_value;
716 f128M_add(&y, &frac, &new_value);
717 y = new_value;
718 }
719 }
720
721 /* Process tail of decimal input so it can affect rounding */
722 if ((a+i & MASK) != z) {
723 uint32_t t = x[a+i & MASK];
724 if (t < 500000000 && (t || (a+i+1 & MASK) != z)) {
725 //frac += 0.25*sign;
726 add_eq_f128_dbl(&frac, 0.25*sign);
727 } else if (t > 500000000) {
728 //frac += 0.75*sign;
729 add_eq_f128_dbl(&frac, 0.75*sign);
730 } else if (t == 500000000) {
731 if ((a+i+1 & MASK) == z) {
732 //frac += 0.5*sign;
733 add_eq_f128_dbl(&frac, 0.5*sign);
734 } else {
735 //frac += 0.75*sign;
736 add_eq_f128_dbl(&frac, 0.75*sign);
737 }
738 }
739 //if (LDBL_MANT_DIG-bits >= 2 && !fmodf128(frac, 1))
740 if (LDBL_MANT_DIG-bits >= 2) {
741 float128_t one;
742 ui32_to_f128M(1, &one);
743 float128_t mod_result = fmodf128(frac, one);
744 if (f128M_eq(&mod_result, &zero)) {
745 //frac++;
746 add_eq_f128_dbl(&frac, 1.0);
747 }
748 }
749 }
750
751 //y += frac;
752 {
753 float128_t new_value;
754 f128M_add(&y, &frac, &new_value);
755 y = new_value;
756 }
757 //y -= bias;
758 {
759 float128_t new_value;
760 f128M_sub(&y, &bias, &new_value);
761 y = new_value;
762 }
763
764 if ((e2+LDBL_MANT_DIG & INT_MAX) > emax-5) {
765 //if (fabsf128(y) >= 0x1p113)
766 float128_t abs_y = fabsf128(y);
767 float128_t mant_f128 = make_f128(0x4070000000000000, 0x0000000000000000);
768 if (!f128M_lt(&abs_y, &mant_f128)) {
769 if (denormal && bits==LDBL_MANT_DIG+e2-emin)
770 denormal = 0;
771 //y *= 0.5;
772 {
773 float128_t point_5 = dbl_to_f128(0.5);
774 float128_t new_value;
775 f128M_mul(&y, &point_5, &new_value);
776 y = new_value;
777 }
778
779 e2++;
780 }
781 if (e2+LDBL_MANT_DIG>emax || (denormal && !f128M_eq(&frac, &zero)))
782 errno = ERANGE;
783 }
784
785 return scalbnf128(y, e2);
786}
787
788static float128_t hexfloat(struct MuslFILE *f, int bits, int emin, int sign, int pok)
789{
790 float128_t zero;
791 ui32_to_f128M(0, &zero);
792 float128_t one;
793 ui32_to_f128M(1, &one);
794 float128_t sixteen;
795 ui32_to_f128M(16, &sixteen);
796 float128_t point_5 = dbl_to_f128(0.5);
797
798 uint32_t x = 0;
799 float128_t y = zero;
800 float128_t scale = one;
801 float128_t bias = zero;
802 int gottail = 0, gotrad = 0, gotdig = 0;
803 long long rp = 0;
804 long long dc = 0;
805 long long e2 = 0;
806 int d;
807 int c;
808
809 c = shgetc(f);
810
811 /* Skip leading zeros/underscores */
812 for (; c=='0' || c=='_'; c = shgetc(f)) gotdig = 1;
813
814 if (c=='.') {
815 gotrad = 1;
816 c = shgetc(f);
817 /* Count zeros after the radix point before significand */
818 for (rp=0; ; c = shgetc(f)) {
819 if (c == '_') {
820 continue;
821 } else if (c == '0') {
822 gotdig = 1;
823 rp--;
824 } else {
825 break;
826 }
827 }
828 }
829
830 for (; c-'0'<10U || (c|32)-'a'<6U || c=='.' || c=='_'; c = shgetc(f)) {
831 if (c=='_') {
832 continue;
833 } else if (c=='.') {
834 if (gotrad) break;
835 rp = dc;
836 gotrad = 1;
837 } else {
838 gotdig = 1;
839 if (c > '9') d = (c|32)+10-'a';
840 else d = c-'0';
841 if (dc<8) {
842 x = x*16 + d;
843 } else if (dc < LDBL_MANT_DIG/4+1) {
844 //y += d*(scale/=16);
845 {
846 float128_t divided;
847 f128M_div(&scale, &sixteen, &divided);
848 scale = divided;
849 float128_t d_f128;
850 i32_to_f128M(d, &d_f128);
851 float128_t add_op;
852 f128M_mul(&d_f128, &scale, &add_op);
853 float128_t new_y;
854 f128M_add(&y, &add_op, &new_y);
855 y = new_y;
856 }
857 } else if (d && !gottail) {
858 //y += 0.5*scale;
859 {
860 float128_t add_op;
861 f128M_mul(&point_5, &scale, &add_op);
862 float128_t new_y;
863 f128M_add(&y, &add_op, &new_y);
864 y = new_y;
865 }
866 gottail = 1;
867 }
868 dc++;
869 }
870 }
871 if (!gotdig) {
872 shunget(f);
873 if (pok) {
874 shunget(f);
875 if (gotrad) shunget(f);
876 } else {
877 shlim(f, 0);
878 }
879 //return sign * 0.0;
880 return dbl_to_f128(sign * 0.0);
881 }
882 if (!gotrad) rp = dc;
883 while (dc<8) x *= 16, dc++;
884 if ((c|32)=='p') {
885 e2 = scanexp(f, pok);
886 if (e2 == LLONG_MIN) {
887 if (pok) {
888 shunget(f);
889 } else {
890 shlim(f, 0);
891 return zero;
892 }
893 e2 = 0;
894 }
895 } else {
896 shunget(f);
897 }
898 e2 += 4*rp - 32;
899
900 if (!x) {
901 //return sign * 0.0;
902 return dbl_to_f128(sign * 0.0);
903 }
904 if (e2 > -emin) {
905 errno = ERANGE;
906 //return sign * LDBL_MAX * LDBL_MAX;
907 return zero;
908 }
909 if (e2 < emin-2*LDBL_MANT_DIG) {
910 errno = ERANGE;
911 //return sign * LDBL_MIN * LDBL_MIN;
912 return zero;
913 }
914
915 while (x < 0x80000000) {
916 //if (y>=0.5)
917 if (!f128M_lt(&y, &point_5)) {
918 x += x + 1;
919 //y += y - 1;
920 {
921 float128_t minus_one;
922 f128M_sub(&y, &one, &minus_one);
923 float128_t new_y;
924 f128M_add(&y, &minus_one, &new_y);
925 y = new_y;
926 }
927 } else {
928 x += x;
929 //y += y;
930 {
931 float128_t new_y;
932 f128M_add(&y, &y, &new_y);
933 y = new_y;
934 }
935 }
936 e2--;
937 }
938
939 if (bits > 32+e2-emin) {
940 bits = 32+e2-emin;
941 if (bits<0) bits=0;
942 }
943
944 if (bits < LDBL_MANT_DIG) {
945 float128_t sign_f128;
946 i32_to_f128M(sign, &sign_f128);
947 bias = copysignf128(dbl_to_f128(scalbn(1, 32+LDBL_MANT_DIG-bits-1)), sign_f128);
948 }
949
950 //if (bits<32 && y && !(x&1)) x++, y=0;
951 if (bits<32 && !f128M_eq(&y, &zero) && !(x&1)) x++, y=zero;
952
953 //y = bias + sign*(float128_t)x + sign*y;
954 {
955 float128_t x_f128;
956 ui32_to_f128M(x, &x_f128);
957 float128_t sign_f128;
958 i32_to_f128M(sign, &sign_f128);
959 float128_t sign_mul_x;
960 f128M_mul(&sign_f128, &x_f128, &sign_mul_x);
961 float128_t sign_mul_y;
962 f128M_mul(&sign_f128, &y, &sign_mul_y);
963 float128_t bias_op;
964 f128M_add(&bias, &sign_mul_x, &bias_op);
965 float128_t new_y;
966 f128M_add(&bias_op, &sign_mul_y, &new_y);
967 y = new_y;
968 }
969 //y -= bias;
970 {
971 float128_t new_y;
972 f128M_sub(&y, &bias, &new_y);
973 y = new_y;
974 }
975
976 if (f128M_eq(&y, &zero)) errno = ERANGE;
977
978 return scalbnf128(y, e2);
979}
980
981static int isspace(int c)
982{
983 return c == ' ' || (unsigned)c-'\t' < 5;
984}
985
986static inline float128_t makeInf128(void) {
987 union ldshape ux;
988 ux.i2.hi = 0x7fff000000000000UL;
989 ux.i2.lo = 0x0UL;
990 return ux.f;
991}
992
993static inline float128_t makeNaN128(void) {
994 uint64_t rand = 0UL;
995 union ldshape ux;
996 ux.i2.hi = 0x7fff000000000000UL | (rand & 0xffffffffffffUL);
997 ux.i2.lo = 0x0UL;
998 return ux.f;
999}
1000
1001float128_t __floatscan(struct MuslFILE *f, int prec, int pok)
1002{
1003 int sign = 1;
1004 size_t i;
1005 int bits = LDBL_MANT_DIG;
1006 int emin = LDBL_MIN_EXP-bits;
1007 int c;
1008
1009 while (isspace((c=shgetc(f))));
1010
1011 if (c=='+' || c=='-') {
1012 sign -= 2*(c=='-');
1013 c = shgetc(f);
1014 }
1015
1016 for (i=0; i<8 && (c|32)=="infinity"[i]; i++)
1017 if (i<7) c = shgetc(f);
1018 if (i==3 || i==8 || (i>3 && pok)) {
1019 if (i!=8) {
1020 shunget(f);
1021 if (pok) for (; i>3; i--) shunget(f);
1022 }
1023 //return sign * INFINITY;
1024 float128_t sign_f128;
1025 i32_to_f128M(sign, &sign_f128);
1026 float128_t infinity_f128 = makeInf128();
1027 float128_t result;
1028 f128M_mul(&sign_f128, &infinity_f128, &result);
1029 return result;
1030 }
1031 if (!i) for (i=0; i<3 && (c|32)=="nan"[i]; i++)
1032 if (i<2) c = shgetc(f);
1033 if (i==3) {
1034 if (shgetc(f) != '(') {
1035 shunget(f);
1036 return makeNaN128();
1037 }
1038 for (i=1; ; i++) {
1039 c = shgetc(f);
1040 if (c-'0'<10U || c-'A'<26U || c-'a'<26U || c=='_')
1041 continue;
1042 if (c==')') return makeNaN128();
1043 shunget(f);
1044 if (!pok) {
1045 errno = EINVAL;
1046 shlim(f, 0);
1047 float128_t zero;
1048 ui32_to_f128M(0, &zero);
1049 return zero;
1050 }
1051 while (i--) shunget(f);
1052 return makeNaN128();
1053 }
1054 return makeNaN128();
1055 }
1056
1057 if (i) {
1058 shunget(f);
1059 errno = EINVAL;
1060 shlim(f, 0);
1061 float128_t zero;
1062 ui32_to_f128M(0, &zero);
1063 return zero;
1064 }
1065
1066 if (c=='0') {
1067 c = shgetc(f);
1068 if ((c|32) == 'x')
1069 return hexfloat(f, bits, emin, sign, pok);
1070 shunget(f);
1071 c = '0';
1072 }
1073
1074 return decfloat(f, c, bits, emin, sign, pok);
1075}
1076
1077float128_t parse_f128(const char *s, char **p) {
1078 struct MuslFILE f;
1079 sh_fromstring(&f, s);
1080 shlim(&f, 0);
1081 float128_t y = __floatscan(&f, 2, 1);
1082 off_t cnt = shcnt(&f);
1083 if (p) *p = cnt ? (char *)s + cnt : (char *)s;
1084 return y;
1085}
src/stage1/parse_f128.h deleted-21
...@@ -1,21 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_PARSE_F128_H
9#define ZIG_PARSE_F128_H
10
11#include "softfloat_types.h"
12
13#ifdef __cplusplus
14#define ZIG_EXTERN_C extern "C"
15#else
16#define ZIG_EXTERN_C
17#endif
18
19ZIG_EXTERN_C float128_t parse_f128(const char *s, char **p);
20
21#endif
src/stage1/parser.cpp deleted-3603
...@@ -1,3603 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "parser.hpp"
9#include "errmsg.hpp"
10#include "analyze.hpp"
11
12#include <stdarg.h>
13#include <stdio.h>
14#include <limits.h>
15#include <errno.h>
16
17struct ParseContext {
18 Buf *buf;
19 // Shortcut to `owner->data.structure.root_struct->token_ids`.
20 TokenId *token_ids;
21 // Shortcut to `owner->data.structure.root_struct->token_locs`.
22 TokenLoc *token_locs;
23 ZigType *owner;
24 TokenIndex current_token;
25 ErrColor err_color;
26 // Shortcut to `owner->data.structure.root_struct->token_count`.
27 uint32_t token_count;
28};
29
30struct PtrPayload {
31 TokenIndex asterisk;
32 TokenIndex payload;
33};
34
35struct PtrIndexPayload {
36 TokenIndex asterisk;
37 TokenIndex payload;
38 TokenIndex index;
39};
40
41static AstNode *ast_parse_root(ParseContext *pc);
42static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc);
43static AstNode *ast_parse_test_decl(ParseContext *pc);
44static AstNode *ast_parse_top_level_comptime(ParseContext *pc);
45static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod,
46 TokenIndex doc_comments);
47static AstNode *ast_parse_fn_proto(ParseContext *pc);
48static AstNode *ast_parse_var_decl(ParseContext *pc);
49static AstNode *ast_parse_container_field(ParseContext *pc);
50static AstNode *ast_parse_statement(ParseContext *pc);
51static AstNode *ast_parse_if_statement(ParseContext *pc);
52static AstNode *ast_parse_labeled_statement(ParseContext *pc);
53static AstNode *ast_parse_loop_statement(ParseContext *pc);
54static AstNode *ast_parse_for_statement(ParseContext *pc);
55static AstNode *ast_parse_while_statement(ParseContext *pc);
56static AstNode *ast_parse_block_expr_statement(ParseContext *pc);
57static AstNode *ast_parse_block_expr(ParseContext *pc);
58static AstNode *ast_parse_assign_expr(ParseContext *pc);
59static AstNode *ast_parse_expr(ParseContext *pc);
60static AstNode *ast_parse_bool_or_expr(ParseContext *pc);
61static AstNode *ast_parse_bool_and_expr(ParseContext *pc);
62static AstNode *ast_parse_compare_expr(ParseContext *pc);
63static AstNode *ast_parse_bitwise_expr(ParseContext *pc);
64static AstNode *ast_parse_bit_shift_expr(ParseContext *pc);
65static AstNode *ast_parse_addition_expr(ParseContext *pc);
66static AstNode *ast_parse_multiply_expr(ParseContext *pc);
67static AstNode *ast_parse_prefix_expr(ParseContext *pc);
68static AstNode *ast_parse_primary_expr(ParseContext *pc);
69static AstNode *ast_parse_if_expr(ParseContext *pc);
70static AstNode *ast_parse_block(ParseContext *pc);
71static AstNode *ast_parse_loop_expr(ParseContext *pc);
72static AstNode *ast_parse_for_expr(ParseContext *pc);
73static AstNode *ast_parse_while_expr(ParseContext *pc);
74static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc);
75static AstNode *ast_parse_init_list(ParseContext *pc);
76static AstNode *ast_parse_type_expr(ParseContext *pc);
77static AstNode *ast_parse_error_union_expr(ParseContext *pc);
78static AstNode *ast_parse_suffix_expr(ParseContext *pc);
79static AstNode *ast_parse_primary_type_expr(ParseContext *pc);
80static AstNode *ast_parse_container_decl(ParseContext *pc);
81static AstNode *ast_parse_error_set_decl(ParseContext *pc);
82static AstNode *ast_parse_grouped_expr(ParseContext *pc);
83static AstNode *ast_parse_if_type_expr(ParseContext *pc);
84static AstNode *ast_parse_labeled_type_expr(ParseContext *pc);
85static AstNode *ast_parse_loop_type_expr(ParseContext *pc);
86static AstNode *ast_parse_for_type_expr(ParseContext *pc);
87static AstNode *ast_parse_while_type_expr(ParseContext *pc);
88static AstNode *ast_parse_switch_expr(ParseContext *pc);
89static AstNode *ast_parse_asm_expr(ParseContext *pc);
90static AstNode *ast_parse_anon_lit(ParseContext *pc);
91static AstNode *ast_parse_asm_output(ParseContext *pc);
92static AsmOutput *ast_parse_asm_output_item(ParseContext *pc);
93static AstNode *ast_parse_asm_input(ParseContext *pc);
94static AsmInput *ast_parse_asm_input_item(ParseContext *pc);
95static AstNode *ast_parse_asm_clobbers(ParseContext *pc);
96static TokenIndex ast_parse_break_label(ParseContext *pc);
97static TokenIndex ast_parse_block_label(ParseContext *pc);
98static AstNode *ast_parse_field_init(ParseContext *pc);
99static AstNode *ast_parse_while_continue_expr(ParseContext *pc);
100static AstNode *ast_parse_link_section(ParseContext *pc);
101static AstNode *ast_parse_callconv(ParseContext *pc);
102static AstNode *ast_parse_param_decl(ParseContext *pc);
103static AstNode *ast_parse_param_type(ParseContext *pc);
104static AstNode *ast_parse_if_prefix(ParseContext *pc);
105static AstNode *ast_parse_while_prefix(ParseContext *pc);
106static AstNode *ast_parse_for_prefix(ParseContext *pc);
107static TokenIndex ast_parse_payload(ParseContext *pc);
108static Optional<PtrPayload> ast_parse_ptr_payload(ParseContext *pc);
109static Optional<PtrIndexPayload> ast_parse_ptr_index_payload(ParseContext *pc);
110static AstNode *ast_parse_switch_prong(ParseContext *pc);
111static AstNode *ast_parse_switch_case(ParseContext *pc);
112static AstNode *ast_parse_switch_item(ParseContext *pc);
113static AstNode *ast_parse_assign_op(ParseContext *pc);
114static AstNode *ast_parse_compare_op(ParseContext *pc);
115static AstNode *ast_parse_bitwise_op(ParseContext *pc);
116static AstNode *ast_parse_bit_shift_op(ParseContext *pc);
117static AstNode *ast_parse_addition_op(ParseContext *pc);
118static AstNode *ast_parse_multiply_op(ParseContext *pc);
119static AstNode *ast_parse_prefix_op(ParseContext *pc);
120static AstNode *ast_parse_prefix_type_op(ParseContext *pc);
121static AstNode *ast_parse_suffix_op(ParseContext *pc);
122static AstNode *ast_parse_fn_call_arguments(ParseContext *pc);
123static AstNode *ast_parse_array_type_start(ParseContext *pc);
124static AstNode *ast_parse_ptr_type_start(ParseContext *pc);
125static AstNode *ast_parse_container_decl_auto(ParseContext *pc);
126static AstNode *ast_parse_container_decl_type(ParseContext *pc);
127static AstNode *ast_parse_byte_align(ParseContext *pc);
128
129ATTRIBUTE_NORETURN
130static void ast_error_offset(RootStruct *root_struct, ErrColor err_color,
131 TokenIndex token, size_t bad_index, Buf *msg)
132{
133 assert(token < root_struct->token_count);
134 uint32_t byte_offset = root_struct->token_locs[token].offset;
135 ErrorMsg *err = err_msg_create_with_offset(root_struct->path,
136 byte_offset + bad_index, buf_ptr(root_struct->source_code), msg);
137
138 print_err_msg(err, err_color);
139 exit(EXIT_FAILURE);
140}
141
142ATTRIBUTE_PRINTF(3, 4)
143ATTRIBUTE_NORETURN
144static void ast_error(ParseContext *pc, TokenIndex token, const char *format, ...) {
145 va_list ap;
146 va_start(ap, format);
147 Buf *msg = buf_vprintf(format, ap);
148 va_end(ap);
149
150 RootStruct *root_struct = pc->owner->data.structure.root_struct;
151 ast_error_offset(root_struct, pc->err_color, token, 0, msg);
152}
153
154ATTRIBUTE_NORETURN
155static void ast_invalid_token_error(ParseContext *pc, TokenIndex token) {
156 ast_error(pc, token, "invalid token: '%s'", token_name(pc->token_ids[token]));
157}
158
159static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) {
160 AstNode *node = heap::c_allocator.create<AstNode>();
161 node->type = type;
162 node->owner = pc->owner;
163 return node;
164}
165
166static AstNode *ast_create_node(ParseContext *pc, NodeType type, TokenIndex first_token) {
167 assert(first_token);
168 AstNode *node = ast_create_node_no_line_info(pc, type);
169 node->main_token = first_token;
170 return node;
171}
172
173static AstNode *ast_create_node_copy_line_info(ParseContext *pc, NodeType type, AstNode *from) {
174 assert(from);
175 AstNode *node = ast_create_node_no_line_info(pc, type);
176 node->main_token = from->main_token;
177 return node;
178}
179
180static TokenIndex peek_token(ParseContext *pc) {
181 return pc->current_token;
182}
183
184static TokenIndex eat_token(ParseContext *pc) {
185 TokenIndex res = peek_token(pc);
186 pc->current_token += 1;
187 return res;
188}
189
190static TokenIndex eat_token_if(ParseContext *pc, TokenId id) {
191 TokenIndex res = peek_token(pc);
192 if (pc->token_ids[res] == id) {
193 return eat_token(pc);
194 }
195
196 return 0;
197}
198
199static TokenIndex expect_token(ParseContext *pc, TokenId id) {
200 TokenIndex res = eat_token(pc);
201 TokenId actual_id = pc->token_ids[res];
202 if (actual_id != id)
203 ast_error(pc, res, "expected token '%s', found '%s'", token_name(id), token_name(actual_id));
204
205 return res;
206}
207
208static void put_back_token(ParseContext *pc) {
209 pc->current_token -= 1;
210}
211
212static Buf *token_buf(ParseContext *pc, TokenIndex token) {
213 Error err;
214
215 if (token == 0)
216 return nullptr;
217
218 RootStruct *root_struct = pc->owner->data.structure.root_struct;
219 if (root_struct->token_ids[token] == TokenIdIdentifier) {
220 return token_identifier_buf(root_struct, token);
221 } else if (root_struct->token_ids[token] == TokenIdStringLiteral) {
222 assert(root_struct->token_ids[token] == TokenIdStringLiteral);
223 const char *source = buf_ptr(root_struct->source_code);
224 size_t byte_offset = root_struct->token_locs[token].offset;
225 size_t bad_index;
226 Buf *str = buf_alloc();
227 if ((err = source_string_literal_buf(source + byte_offset, str, &bad_index))) {
228 ast_error_offset(root_struct, pc->err_color, token, bad_index,
229 buf_create_from_str("invalid string literal character"));
230 }
231 return str;
232 } else {
233 zig_unreachable();
234 }
235}
236
237static AstNode *token_identifier(ParseContext *pc, TokenIndex token) {
238 assert(pc->token_ids[token] == TokenIdIdentifier);
239 return ast_create_node(pc, NodeTypeIdentifier, token);
240}
241
242// (Rule SEP)* Rule?
243template<typename T>
244static ZigList<T *> ast_parse_list(ParseContext *pc, TokenId sep, T *(*parser)(ParseContext*)) {
245 ZigList<T *> res = {};
246 while (true) {
247 T *curr = parser(pc);
248 if (curr == nullptr)
249 break;
250
251 res.append(curr);
252 if (eat_token_if(pc, sep) == 0)
253 break;
254 }
255
256 return res;
257}
258
259static AstNode *ast_expect(ParseContext *pc, AstNode *(*parser)(ParseContext*)) {
260 AstNode *res = parser(pc);
261 if (res == nullptr)
262 ast_invalid_token_error(pc, peek_token(pc));
263 return res;
264}
265
266enum BinOpChain {
267 BinOpChainOnce,
268 BinOpChainInf,
269};
270
271// Op* Child
272static AstNode *ast_parse_prefix_op_expr(
273 ParseContext *pc,
274 AstNode *(*op_parser)(ParseContext *),
275 AstNode *(*child_parser)(ParseContext *)
276) {
277 AstNode *res = nullptr;
278 AstNode **right = &res;
279 while (true) {
280 AstNode *prefix = op_parser(pc);
281 if (prefix == nullptr)
282 break;
283
284 *right = prefix;
285 switch (prefix->type) {
286 case NodeTypePrefixOpExpr:
287 right = &prefix->data.prefix_op_expr.primary_expr;
288 break;
289 case NodeTypeReturnExpr:
290 right = &prefix->data.return_expr.expr;
291 break;
292 case NodeTypeAwaitExpr:
293 right = &prefix->data.await_expr.expr;
294 break;
295 case NodeTypeAnyFrameType:
296 right = &prefix->data.anyframe_type.payload_type;
297 break;
298 case NodeTypeArrayType:
299 right = &prefix->data.array_type.child_type;
300 break;
301 case NodeTypeInferredArrayType:
302 right = &prefix->data.inferred_array_type.child_type;
303 break;
304 case NodeTypePointerType: {
305 // We might get two pointers from *_ptr_type_start
306 AstNode *child = prefix->data.pointer_type.op_expr;
307 if (child == nullptr)
308 child = prefix;
309 right = &child->data.pointer_type.op_expr;
310 break;
311 }
312 default:
313 zig_unreachable();
314 }
315 }
316
317 // If we have already consumed a token, and determined that
318 // this node is a prefix op, then we expect that the node has
319 // a child.
320 if (res != nullptr) {
321 *right = ast_expect(pc, child_parser);
322 } else {
323 // Otherwise, if we didn't consume a token, then we can return
324 // null, if the child expr did.
325 *right = child_parser(pc);
326 if (*right == nullptr)
327 return nullptr;
328 }
329
330 return res;
331}
332
333// Child (Op Child)(*/?)
334static AstNode *ast_parse_bin_op_expr(
335 ParseContext *pc,
336 BinOpChain chain,
337 AstNode *(*op_parse)(ParseContext*),
338 AstNode *(*child_parse)(ParseContext*)
339) {
340 AstNode *res = child_parse(pc);
341 if (res == nullptr)
342 return nullptr;
343
344 do {
345 AstNode *op = op_parse(pc);
346 if (op == nullptr)
347 break;
348
349 AstNode *left = res;
350 AstNode *right = ast_expect(pc, child_parse);
351 res = op;
352 switch (op->type) {
353 case NodeTypeBinOpExpr:
354 op->data.bin_op_expr.op1 = left;
355 op->data.bin_op_expr.op2 = right;
356 break;
357 case NodeTypeCatchExpr:
358 op->data.unwrap_err_expr.op1 = left;
359 op->data.unwrap_err_expr.op2 = right;
360 break;
361 default:
362 zig_unreachable();
363 }
364 } while (chain == BinOpChainInf);
365
366 return res;
367}
368
369// IfPrefix Body (KEYWORD_else Payload? Body)?
370static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parser)(ParseContext*)) {
371 AstNode *res = ast_parse_if_prefix(pc);
372 if (res == nullptr)
373 return nullptr;
374
375 AstNode *body = ast_expect(pc, body_parser);
376 TokenIndex err_payload = 0;
377 AstNode *else_body = nullptr;
378 if (eat_token_if(pc, TokenIdKeywordElse) != 0) {
379 err_payload = ast_parse_payload(pc);
380 else_body = ast_expect(pc, body_parser);
381 }
382
383 assert(res->type == NodeTypeIfOptional);
384 if (err_payload != 0) {
385 AstNodeTestExpr old = res->data.test_expr;
386 res->type = NodeTypeIfErrorExpr;
387 res->data.if_err_expr.target_node = old.target_node;
388 res->data.if_err_expr.var_is_ptr = old.var_is_ptr;
389 res->data.if_err_expr.var_symbol = old.var_symbol;
390 res->data.if_err_expr.then_node = body;
391 res->data.if_err_expr.err_symbol = token_buf(pc, err_payload);
392 res->data.if_err_expr.else_node = else_body;
393 return res;
394 }
395
396 if (res->data.test_expr.var_symbol != nullptr) {
397 res->data.test_expr.then_node = body;
398 res->data.test_expr.else_node = else_body;
399 return res;
400 }
401
402 AstNodeTestExpr old = res->data.test_expr;
403 res->type = NodeTypeIfBoolExpr;
404 res->data.if_bool_expr.condition = old.target_node;
405 res->data.if_bool_expr.then_block = body;
406 res->data.if_bool_expr.else_node = else_body;
407 return res;
408}
409
410// KEYWORD_inline? (ForLoop / WhileLoop)
411static AstNode *ast_parse_loop_expr_helper(
412 ParseContext *pc,
413 AstNode *(*for_parser)(ParseContext *),
414 AstNode *(*while_parser)(ParseContext *)
415) {
416 TokenIndex inline_token = eat_token_if(pc, TokenIdKeywordInline);
417 AstNode *for_expr = for_parser(pc);
418 if (for_expr != nullptr) {
419 assert(for_expr->type == NodeTypeForExpr);
420 for_expr->data.for_expr.is_inline = inline_token != 0;
421 return for_expr;
422 }
423
424 AstNode *while_expr = while_parser(pc);
425 if (while_expr != nullptr) {
426 assert(while_expr->type == NodeTypeWhileExpr);
427 while_expr->data.while_expr.is_inline = inline_token != 0;
428 return while_expr;
429 }
430
431 if (inline_token != 0)
432 ast_invalid_token_error(pc, peek_token(pc));
433 return nullptr;
434}
435
436// ForPrefix Body (KEYWORD_else Body)?
437static AstNode *ast_parse_for_expr_helper(ParseContext *pc, AstNode *(*body_parser)(ParseContext*)) {
438 AstNode *res = ast_parse_for_prefix(pc);
439 if (res == nullptr)
440 return nullptr;
441
442 AstNode *body = ast_expect(pc, body_parser);
443 AstNode *else_body = nullptr;
444 if (eat_token_if(pc, TokenIdKeywordElse) != 0)
445 else_body = ast_expect(pc, body_parser);
446
447 assert(res->type == NodeTypeForExpr);
448 res->data.for_expr.body = body;
449 res->data.for_expr.else_node = else_body;
450 return res;
451}
452
453// WhilePrefix Body (KEYWORD_else Payload? Body)?
454static AstNode *ast_parse_while_expr_helper(ParseContext *pc, AstNode *(*body_parser)(ParseContext*)) {
455 AstNode *res = ast_parse_while_prefix(pc);
456 if (res == nullptr)
457 return nullptr;
458
459 AstNode *body = ast_expect(pc, body_parser);
460 TokenIndex err_payload = 0;
461 AstNode *else_body = nullptr;
462 if (eat_token_if(pc, TokenIdKeywordElse) != 0) {
463 err_payload = ast_parse_payload(pc);
464 else_body = ast_expect(pc, body_parser);
465 }
466
467 assert(res->type == NodeTypeWhileExpr);
468 res->data.while_expr.body = body;
469 res->data.while_expr.err_symbol = token_buf(pc, err_payload);
470 res->data.while_expr.else_node = else_body;
471 return res;
472}
473
474template<TokenId id, BinOpType op>
475AstNode *ast_parse_bin_op_simple(ParseContext *pc) {
476 TokenIndex op_token = eat_token_if(pc, id);
477 if (op_token == 0)
478 return nullptr;
479
480 AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
481 res->data.bin_op_expr.bin_op = op;
482 return res;
483}
484
485AstNode *ast_parse(Buf *buf, ZigType *owner, ErrColor err_color) {
486 RootStruct *root_struct = owner->data.structure.root_struct;
487
488 ParseContext pc = {};
489 pc.err_color = err_color;
490 pc.owner = owner;
491 pc.buf = buf;
492 pc.token_ids = root_struct->token_ids;
493 pc.token_locs = root_struct->token_locs;
494 pc.token_count = root_struct->token_count;
495 pc.current_token = 1; // Skip over the first (invalid) token.
496 return ast_parse_root(&pc);
497}
498
499// Root <- skip ContainerMembers eof
500static AstNode *ast_parse_root(ParseContext *pc) {
501 TokenIndex first = peek_token(pc);
502 AstNodeContainerDecl members = ast_parse_container_members(pc);
503 if (pc->current_token != pc->token_count - 1)
504 ast_invalid_token_error(pc, peek_token(pc));
505
506 AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first);
507 node->data.container_decl.fields = members.fields;
508 node->data.container_decl.decls = members.decls;
509 node->data.container_decl.layout = ContainerLayoutAuto;
510 node->data.container_decl.kind = ContainerKindStruct;
511 node->data.container_decl.is_root = true;
512 node->data.container_decl.doc_comments = members.doc_comments;
513
514 return node;
515}
516
517static TokenIndex ast_parse_multi_tok(ParseContext *pc, TokenId token_id) {
518 TokenIndex first_token = eat_token_if(pc, token_id);
519 TokenIndex token = first_token;
520 while (token != 0) {
521 token = eat_token_if(pc, token_id);
522 }
523 return first_token;
524}
525
526static TokenIndex ast_parse_doc_comments(ParseContext *pc) {
527 return ast_parse_multi_tok(pc, TokenIdDocComment);
528}
529
530static TokenIndex ast_parse_container_doc_comments(ParseContext *pc) {
531 return ast_parse_multi_tok(pc, TokenIdContainerDocComment);
532}
533
534enum ContainerFieldState {
535 // no fields have been seen
536 ContainerFieldStateNone,
537 // currently parsing fields
538 ContainerFieldStateSeen,
539 // saw fields and then a declaration after them
540 ContainerFieldStateEnd,
541};
542
543// ContainerMembers
544// <- TestDecl ContainerMembers
545// / TopLevelComptime ContainerMembers
546// / KEYWORD_pub? TopLevelDecl ContainerMembers
547// / ContainerField COMMA ContainerMembers
548// / ContainerField
549// /
550static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {
551 AstNodeContainerDecl res = {};
552 ContainerFieldState field_state = ContainerFieldStateNone;
553 TokenIndex first_token = 0;
554 res.doc_comments = ast_parse_container_doc_comments(pc);
555 for (;;) {
556 TokenIndex peeked_token = peek_token(pc);
557
558 AstNode *test_decl = ast_parse_test_decl(pc);
559 if (test_decl != nullptr) {
560 if (field_state == ContainerFieldStateSeen) {
561 field_state = ContainerFieldStateEnd;
562 first_token = peeked_token;
563 }
564 res.decls.append(test_decl);
565 continue;
566 }
567
568 AstNode *top_level_comptime = ast_parse_top_level_comptime(pc);
569 if (top_level_comptime != nullptr) {
570 if (field_state == ContainerFieldStateSeen) {
571 field_state = ContainerFieldStateEnd;
572 first_token = peeked_token;
573 }
574 res.decls.append(top_level_comptime);
575 continue;
576 }
577
578 TokenIndex first_doc_token = ast_parse_doc_comments(pc);
579
580 peeked_token = peek_token(pc);
581
582 TokenIndex visib_token = eat_token_if(pc, TokenIdKeywordPub);
583 VisibMod visib_mod = (visib_token != 0) ? VisibModPub : VisibModPrivate;
584
585 AstNode *top_level_decl = ast_parse_top_level_decl(pc, visib_mod, first_doc_token);
586 if (top_level_decl != nullptr) {
587 if (field_state == ContainerFieldStateSeen) {
588 field_state = ContainerFieldStateEnd;
589 first_token = peeked_token;
590 }
591 res.decls.append(top_level_decl);
592 continue;
593 }
594
595 if (visib_token != 0) {
596 ast_error(pc, peek_token(pc), "expected function or variable declaration after pub");
597 }
598
599 TokenIndex comptime_token = eat_token_if(pc, TokenIdKeywordCompTime);
600
601 AstNode *container_field = ast_parse_container_field(pc);
602 if (container_field != nullptr) {
603 switch (field_state) {
604 case ContainerFieldStateNone:
605 field_state = ContainerFieldStateSeen;
606 break;
607 case ContainerFieldStateSeen:
608 break;
609 case ContainerFieldStateEnd:
610 ast_error(pc, first_token, "declarations are not allowed between container fields");
611 }
612
613 assert(container_field->type == NodeTypeStructField);
614 container_field->data.struct_field.doc_comments = first_doc_token;
615 container_field->data.struct_field.comptime_token = comptime_token;
616 res.fields.append(container_field);
617 if (eat_token_if(pc, TokenIdComma) != 0) {
618 continue;
619 } else {
620 break;
621 }
622 }
623
624 break;
625 }
626 return res;
627}
628
629// TestDecl <- KEYWORD_test STRINGLITERALSINGLE? Block
630static AstNode *ast_parse_test_decl(ParseContext *pc) {
631 TokenIndex test = eat_token_if(pc, TokenIdKeywordTest);
632 if (test == 0)
633 return nullptr;
634
635 TokenIndex name = eat_token_if(pc, TokenIdStringLiteral);
636 AstNode *block = ast_expect(pc, ast_parse_block);
637 AstNode *res = ast_create_node(pc, NodeTypeTestDecl, test);
638 res->data.test_decl.name = name ? token_buf(pc, name) : nullptr;
639 res->data.test_decl.body = block;
640 return res;
641}
642
643// TopLevelComptime <- KEYWORD_comptime BlockExpr
644static AstNode *ast_parse_top_level_comptime(ParseContext *pc) {
645 TokenIndex comptime = eat_token_if(pc, TokenIdKeywordCompTime);
646 if (comptime == 0)
647 return nullptr;
648
649 // 1 token lookahead because it could be a comptime struct field
650 TokenIndex lbrace = peek_token(pc);
651 if (pc->token_ids[lbrace] != TokenIdLBrace) {
652 put_back_token(pc);
653 return nullptr;
654 }
655
656 AstNode *block = ast_expect(pc, ast_parse_block_expr);
657 AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime);
658 res->data.comptime_expr.expr = block;
659 return res;
660}
661
662// TopLevelDecl
663// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block)
664// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl
665// / KEYWORD_use Expr SEMICOLON
666static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod,
667 TokenIndex doc_comments)
668{
669 TokenIndex first = eat_token_if(pc, TokenIdKeywordExport);
670 if (first == 0)
671 first = eat_token_if(pc, TokenIdKeywordExtern);
672 if (first == 0)
673 first = eat_token_if(pc, TokenIdKeywordInline);
674 if (first == 0)
675 first = eat_token_if(pc, TokenIdKeywordNoInline);
676 if (first != 0) {
677 TokenIndex lib_name = 0;
678 if (pc->token_ids[first] == TokenIdKeywordExtern)
679 lib_name = eat_token_if(pc, TokenIdStringLiteral);
680
681 if (pc->token_ids[first] != TokenIdKeywordNoInline && pc->token_ids[first] != TokenIdKeywordInline) {
682 TokenIndex thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
683 AstNode *var_decl = ast_parse_var_decl(pc);
684 if (var_decl != nullptr) {
685 assert(var_decl->type == NodeTypeVariableDeclaration);
686 if (pc->token_ids[first] == TokenIdKeywordExtern && var_decl->data.variable_declaration.expr != nullptr) {
687 ast_error(pc, first, "extern variables have no initializers");
688 }
689 var_decl->main_token = first;
690 var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;
691 var_decl->data.variable_declaration.visib_mod = visib_mod;
692 var_decl->data.variable_declaration.doc_comments = doc_comments;
693 var_decl->data.variable_declaration.is_extern = pc->token_ids[first] == TokenIdKeywordExtern;
694 var_decl->data.variable_declaration.is_export = pc->token_ids[first] == TokenIdKeywordExport;
695 var_decl->data.variable_declaration.lib_name = token_buf(pc, lib_name);
696 return var_decl;
697 }
698
699 if (thread_local_kw != 0)
700 put_back_token(pc);
701 }
702
703 AstNode *fn_proto = ast_parse_fn_proto(pc);
704 if (fn_proto != nullptr) {
705 AstNode *body = ast_parse_block(pc);
706 if (body == nullptr)
707 expect_token(pc, TokenIdSemicolon);
708
709 assert(fn_proto->type == NodeTypeFnProto);
710 fn_proto->main_token = first;
711 fn_proto->data.fn_proto.visib_mod = visib_mod;
712 fn_proto->data.fn_proto.doc_comments = doc_comments;
713 if (!fn_proto->data.fn_proto.is_extern)
714 fn_proto->data.fn_proto.is_extern = pc->token_ids[first] == TokenIdKeywordExtern;
715 fn_proto->data.fn_proto.is_export = pc->token_ids[first] == TokenIdKeywordExport;
716 switch (pc->token_ids[first]) {
717 case TokenIdKeywordInline:
718 fn_proto->data.fn_proto.fn_inline = FnInlineAlways;
719 break;
720 case TokenIdKeywordNoInline:
721 fn_proto->data.fn_proto.fn_inline = FnInlineNever;
722 break;
723 default:
724 fn_proto->data.fn_proto.fn_inline = FnInlineAuto;
725 break;
726 }
727 fn_proto->data.fn_proto.lib_name = token_buf(pc, lib_name);
728
729 AstNode *res = fn_proto;
730 if (body != nullptr) {
731 if (fn_proto->data.fn_proto.is_extern) {
732 ast_error(pc, first, "extern functions have no body");
733 }
734 res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto);
735 res->data.fn_def.fn_proto = fn_proto;
736 res->data.fn_def.body = body;
737 fn_proto->data.fn_proto.fn_def_node = res;
738 }
739
740 return res;
741 }
742
743 ast_invalid_token_error(pc, peek_token(pc));
744 }
745
746 TokenIndex thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
747 AstNode *var_decl = ast_parse_var_decl(pc);
748 if (var_decl != nullptr) {
749 assert(var_decl->type == NodeTypeVariableDeclaration);
750 var_decl->data.variable_declaration.visib_mod = visib_mod;
751 var_decl->data.variable_declaration.doc_comments = doc_comments;
752 var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;
753 return var_decl;
754 }
755
756 if (thread_local_kw != 0)
757 put_back_token(pc);
758
759 AstNode *fn_proto = ast_parse_fn_proto(pc);
760 if (fn_proto != nullptr) {
761 AstNode *body = ast_parse_block(pc);
762 if (body == nullptr)
763 expect_token(pc, TokenIdSemicolon);
764
765 assert(fn_proto->type == NodeTypeFnProto);
766 fn_proto->data.fn_proto.visib_mod = visib_mod;
767 fn_proto->data.fn_proto.doc_comments = doc_comments;
768 AstNode *res = fn_proto;
769 if (body != nullptr) {
770 res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto);
771 res->data.fn_def.fn_proto = fn_proto;
772 res->data.fn_def.body = body;
773 fn_proto->data.fn_proto.fn_def_node = res;
774 }
775
776 return res;
777 }
778
779 TokenIndex usingnamespace = eat_token_if(pc, TokenIdKeywordUsingNamespace);
780 if (usingnamespace != 0) {
781 AstNode *expr = ast_expect(pc, ast_parse_expr);
782 expect_token(pc, TokenIdSemicolon);
783
784 AstNode *res = ast_create_node(pc, NodeTypeUsingNamespace, usingnamespace);
785 res->data.using_namespace.visib_mod = visib_mod;
786 res->data.using_namespace.expr = expr;
787 return res;
788 }
789
790 return nullptr;
791}
792
793// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_anytype / TypeExpr)
794static AstNode *ast_parse_fn_proto(ParseContext *pc) {
795 TokenIndex first = eat_token_if(pc, TokenIdKeywordFn);
796 if (first == 0) {
797 return nullptr;
798 }
799
800 TokenIndex identifier = eat_token_if(pc, TokenIdIdentifier);
801 expect_token(pc, TokenIdLParen);
802 ZigList<AstNode *> params = ast_parse_list(pc, TokenIdComma, ast_parse_param_decl);
803 expect_token(pc, TokenIdRParen);
804
805 AstNode *align_expr = ast_parse_byte_align(pc);
806 AstNode *section_expr = ast_parse_link_section(pc);
807 AstNode *callconv_expr = ast_parse_callconv(pc);
808 TokenIndex exmark = 0;
809 AstNode *return_type = nullptr;
810
811 exmark = eat_token_if(pc, TokenIdBang);
812 return_type = ast_parse_type_expr(pc);
813 if (return_type == nullptr) {
814 TokenIndex next = peek_token(pc);
815 ast_error(
816 pc,
817 next,
818 "expected return type (use 'void' to return nothing), found: '%s'",
819 token_name(pc->token_ids[next])
820 );
821 }
822
823 AstNode *res = ast_create_node(pc, NodeTypeFnProto, first);
824 res->data.fn_proto = {};
825 res->data.fn_proto.name = token_buf(pc, identifier);
826 res->data.fn_proto.params = params;
827 res->data.fn_proto.align_expr = align_expr;
828 res->data.fn_proto.section_expr = section_expr;
829 res->data.fn_proto.callconv_expr = callconv_expr;
830 res->data.fn_proto.auto_err_set = exmark != 0;
831 res->data.fn_proto.return_type = return_type;
832
833 for (size_t i = 0; i < params.length; i++) {
834 AstNode *param_decl = params.at(i);
835 assert(param_decl->type == NodeTypeParamDecl);
836 if (param_decl->data.param_decl.is_var_args)
837 res->data.fn_proto.is_var_args = true;
838 if (i != params.length - 1 && res->data.fn_proto.is_var_args)
839 ast_error(pc, first, "Function prototype have varargs as a none last parameter.");
840 }
841 return res;
842}
843
844// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
845static AstNode *ast_parse_var_decl(ParseContext *pc) {
846 TokenIndex mut_kw = eat_token_if(pc, TokenIdKeywordConst);
847 if (mut_kw == 0)
848 mut_kw = eat_token_if(pc, TokenIdKeywordVar);
849 if (mut_kw == 0)
850 return nullptr;
851
852 TokenIndex identifier = expect_token(pc, TokenIdIdentifier);
853 AstNode *type_expr = nullptr;
854 if (eat_token_if(pc, TokenIdColon) != 0)
855 type_expr = ast_expect(pc, ast_parse_type_expr);
856
857 AstNode *align_expr = ast_parse_byte_align(pc);
858 AstNode *section_expr = ast_parse_link_section(pc);
859 AstNode *expr = nullptr;
860 if (eat_token_if(pc, TokenIdEq) != 0)
861 expr = ast_expect(pc, ast_parse_expr);
862
863 expect_token(pc, TokenIdSemicolon);
864
865 AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw);
866 res->data.variable_declaration.is_const = pc->token_ids[mut_kw] == TokenIdKeywordConst;
867 res->data.variable_declaration.symbol = token_buf(pc, identifier);
868 res->data.variable_declaration.type = type_expr;
869 res->data.variable_declaration.align_expr = align_expr;
870 res->data.variable_declaration.section_expr = section_expr;
871 res->data.variable_declaration.expr = expr;
872 return res;
873}
874
875// ContainerField <- KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
876static AstNode *ast_parse_container_field(ParseContext *pc) {
877 TokenIndex identifier = eat_token_if(pc, TokenIdIdentifier);
878 if (identifier == 0)
879 return nullptr;
880
881 AstNode *type_expr = nullptr;
882 if (eat_token_if(pc, TokenIdColon) != 0) {
883 TokenIndex anytype_tok = eat_token_if(pc, TokenIdKeywordAnyType);
884 if (anytype_tok != 0) {
885 type_expr = ast_create_node(pc, NodeTypeAnyTypeField, anytype_tok);
886 } else {
887 type_expr = ast_expect(pc, ast_parse_type_expr);
888 }
889 }
890 AstNode *align_expr = ast_parse_byte_align(pc);
891 AstNode *expr = nullptr;
892 if (eat_token_if(pc, TokenIdEq) != 0)
893 expr = ast_expect(pc, ast_parse_expr);
894
895 AstNode *res = ast_create_node(pc, NodeTypeStructField, identifier);
896 res->data.struct_field.name = token_buf(pc, identifier);
897 res->data.struct_field.type = type_expr;
898 res->data.struct_field.value = expr;
899 res->data.struct_field.align_expr = align_expr;
900 return res;
901}
902
903// Statement
904// <- KEYWORD_comptime? VarDecl
905// / KEYWORD_comptime BlockExprStatement
906// / KEYWORD_nosuspend BlockExprStatement
907// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
908// / KEYWORD_defer BlockExprStatement
909// / KEYWORD_errdefer Payload? BlockExprStatement
910// / IfStatement
911// / LabeledStatement
912// / SwitchExpr
913// / AssignExpr SEMICOLON
914static AstNode *ast_parse_statement(ParseContext *pc) {
915 TokenIndex comptime = eat_token_if(pc, TokenIdKeywordCompTime);
916 AstNode *var_decl = ast_parse_var_decl(pc);
917 if (var_decl != nullptr) {
918 assert(var_decl->type == NodeTypeVariableDeclaration);
919 var_decl->data.variable_declaration.is_comptime = comptime != 0;
920 return var_decl;
921 }
922
923 if (comptime != 0) {
924 AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
925 AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime);
926 res->data.comptime_expr.expr = statement;
927 return res;
928 }
929
930 TokenIndex nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend);
931 if (nosuspend != 0) {
932 AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
933 AstNode *res = ast_create_node(pc, NodeTypeNoSuspend, nosuspend);
934 res->data.nosuspend_expr.expr = statement;
935 return res;
936 }
937
938 TokenIndex suspend = eat_token_if(pc, TokenIdKeywordSuspend);
939 if (suspend != 0) {
940 AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
941 AstNode *res = ast_create_node(pc, NodeTypeSuspend, suspend);
942 res->data.suspend.block = statement;
943 return res;
944 }
945
946 TokenIndex defer = eat_token_if(pc, TokenIdKeywordDefer);
947 if (defer == 0)
948 defer = eat_token_if(pc, TokenIdKeywordErrdefer);
949 if (defer != 0) {
950 TokenIndex payload = (pc->token_ids[defer] == TokenIdKeywordErrdefer) ?
951 ast_parse_payload(pc) : 0;
952 AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
953 AstNode *res = ast_create_node(pc, NodeTypeDefer, defer);
954
955 res->data.defer.kind = ReturnKindUnconditional;
956 res->data.defer.expr = statement;
957 if (pc->token_ids[defer] == TokenIdKeywordErrdefer) {
958 res->data.defer.kind = ReturnKindError;
959 if (payload != 0)
960 res->data.defer.err_payload = token_identifier(pc, payload);
961 }
962 return res;
963 }
964
965 AstNode *if_statement = ast_parse_if_statement(pc);
966 if (if_statement != nullptr)
967 return if_statement;
968
969 AstNode *labeled_statement = ast_parse_labeled_statement(pc);
970 if (labeled_statement != nullptr)
971 return labeled_statement;
972
973 AstNode *switch_expr = ast_parse_switch_expr(pc);
974 if (switch_expr != nullptr)
975 return switch_expr;
976
977 AstNode *assign = ast_parse_assign_expr(pc);
978 if (assign != nullptr) {
979 expect_token(pc, TokenIdSemicolon);
980 return assign;
981 }
982
983 return nullptr;
984}
985
986// IfStatement
987// <- IfPrefix BlockExpr ( KEYWORD_else Payload? Statement )?
988// / IfPrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
989static AstNode *ast_parse_if_statement(ParseContext *pc) {
990 AstNode *res = ast_parse_if_prefix(pc);
991 if (res == nullptr)
992 return nullptr;
993
994 AstNode *body = ast_parse_block_expr(pc);
995 bool requires_semi = false;
996 if (body == nullptr) {
997 requires_semi = true;
998 body = ast_parse_assign_expr(pc);
999 }
1000
1001 if (body == nullptr) {
1002 TokenIndex tok = eat_token(pc);
1003 ast_error(pc, tok, "expected if body, found '%s'", token_name(pc->token_ids[tok]));
1004 }
1005
1006 TokenIndex err_payload = 0;
1007 AstNode *else_body = nullptr;
1008 if (eat_token_if(pc, TokenIdKeywordElse) != 0) {
1009 err_payload = ast_parse_payload(pc);
1010 else_body = ast_expect(pc, ast_parse_statement);
1011 }
1012
1013 if (requires_semi && else_body == nullptr)
1014 expect_token(pc, TokenIdSemicolon);
1015
1016 assert(res->type == NodeTypeIfOptional);
1017 if (err_payload != 0) {
1018 AstNodeTestExpr old = res->data.test_expr;
1019 res->type = NodeTypeIfErrorExpr;
1020 res->data.if_err_expr.target_node = old.target_node;
1021 res->data.if_err_expr.var_is_ptr = old.var_is_ptr;
1022 res->data.if_err_expr.var_symbol = old.var_symbol;
1023 res->data.if_err_expr.then_node = body;
1024 res->data.if_err_expr.err_symbol = token_buf(pc, err_payload);
1025 res->data.if_err_expr.else_node = else_body;
1026 return res;
1027 }
1028
1029 if (res->data.test_expr.var_symbol != nullptr) {
1030 res->data.test_expr.then_node = body;
1031 res->data.test_expr.else_node = else_body;
1032 return res;
1033 }
1034
1035 AstNodeTestExpr old = res->data.test_expr;
1036 res->type = NodeTypeIfBoolExpr;
1037 res->data.if_bool_expr.condition = old.target_node;
1038 res->data.if_bool_expr.then_block = body;
1039 res->data.if_bool_expr.else_node = else_body;
1040 return res;
1041}
1042
1043// LabeledStatement <- BlockLabel? (Block / LoopStatement)
1044static AstNode *ast_parse_labeled_statement(ParseContext *pc) {
1045 TokenIndex label = ast_parse_block_label(pc);
1046 AstNode *block = ast_parse_block(pc);
1047 if (block != nullptr) {
1048 assert(block->type == NodeTypeBlock);
1049 block->data.block.name = token_buf(pc, label);
1050 return block;
1051 }
1052
1053 AstNode *loop = ast_parse_loop_statement(pc);
1054 if (loop != nullptr) {
1055 switch (loop->type) {
1056 case NodeTypeForExpr:
1057 loop->data.for_expr.name = token_buf(pc, label);
1058 break;
1059 case NodeTypeWhileExpr:
1060 loop->data.while_expr.name = token_buf(pc, label);
1061 break;
1062 default:
1063 zig_unreachable();
1064 }
1065 return loop;
1066 }
1067
1068 if (label != 0)
1069 ast_invalid_token_error(pc, peek_token(pc));
1070 return nullptr;
1071}
1072
1073// LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement)
1074static AstNode *ast_parse_loop_statement(ParseContext *pc) {
1075 TokenIndex inline_token = eat_token_if(pc, TokenIdKeywordInline);
1076 AstNode *for_statement = ast_parse_for_statement(pc);
1077 if (for_statement != nullptr) {
1078 assert(for_statement->type == NodeTypeForExpr);
1079 for_statement->data.for_expr.is_inline = inline_token != 0;
1080 return for_statement;
1081 }
1082
1083 AstNode *while_statement = ast_parse_while_statement(pc);
1084 if (while_statement != nullptr) {
1085 assert(while_statement->type == NodeTypeWhileExpr);
1086 while_statement->data.while_expr.is_inline = inline_token != 0;
1087 return while_statement;
1088 }
1089
1090 if (inline_token != 0)
1091 ast_invalid_token_error(pc, peek_token(pc));
1092 return nullptr;
1093}
1094
1095// ForStatement
1096// <- ForPrefix BlockExpr ( KEYWORD_else Statement )?
1097// / ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement )
1098static AstNode *ast_parse_for_statement(ParseContext *pc) {
1099 AstNode *res = ast_parse_for_prefix(pc);
1100 if (res == nullptr)
1101 return nullptr;
1102
1103 AstNode *body = ast_parse_block_expr(pc);
1104 bool requires_semi = false;
1105 if (body == nullptr) {
1106 requires_semi = true;
1107 body = ast_parse_assign_expr(pc);
1108 }
1109
1110 if (body == nullptr) {
1111 TokenIndex tok = eat_token(pc);
1112 ast_error(pc, tok, "expected loop body, found '%s'", token_name(pc->token_ids[tok]));
1113 }
1114
1115 AstNode *else_body = nullptr;
1116 if (eat_token_if(pc, TokenIdKeywordElse) != 0) {
1117 else_body = ast_expect(pc, ast_parse_statement);
1118 }
1119
1120 if (requires_semi && else_body == nullptr)
1121 expect_token(pc, TokenIdSemicolon);
1122
1123 assert(res->type == NodeTypeForExpr);
1124 res->data.for_expr.body = body;
1125 res->data.for_expr.else_node = else_body;
1126 return res;
1127}
1128
1129// WhileStatement
1130// <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )?
1131// / WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
1132static AstNode *ast_parse_while_statement(ParseContext *pc) {
1133 AstNode *res = ast_parse_while_prefix(pc);
1134 if (res == nullptr)
1135 return nullptr;
1136
1137 AstNode *body = ast_parse_block_expr(pc);
1138 bool requires_semi = false;
1139 if (body == nullptr) {
1140 requires_semi = true;
1141 body = ast_parse_assign_expr(pc);
1142 }
1143
1144 if (body == nullptr) {
1145 TokenIndex tok = eat_token(pc);
1146 ast_error(pc, tok, "expected loop body, found '%s'", token_name(pc->token_ids[tok]));
1147 }
1148
1149 TokenIndex err_payload = 0;
1150 AstNode *else_body = nullptr;
1151 if (eat_token_if(pc, TokenIdKeywordElse) != 0) {
1152 err_payload = ast_parse_payload(pc);
1153 else_body = ast_expect(pc, ast_parse_statement);
1154 }
1155
1156 if (requires_semi && else_body == nullptr)
1157 expect_token(pc, TokenIdSemicolon);
1158
1159 assert(res->type == NodeTypeWhileExpr);
1160 res->data.while_expr.body = body;
1161 res->data.while_expr.err_symbol = token_buf(pc, err_payload);
1162 res->data.while_expr.else_node = else_body;
1163 return res;
1164}
1165
1166
1167// BlockExprStatement
1168// <- BlockExpr
1169// / AssignExpr SEMICOLON
1170static AstNode *ast_parse_block_expr_statement(ParseContext *pc) {
1171 AstNode *block = ast_parse_block_expr(pc);
1172 if (block != nullptr)
1173 return block;
1174
1175 AstNode *assign_expr = ast_parse_assign_expr(pc);
1176 if (assign_expr != nullptr) {
1177 expect_token(pc, TokenIdSemicolon);
1178 return assign_expr;
1179 }
1180
1181 return nullptr;
1182}
1183
1184// BlockExpr <- BlockLabel? Block
1185static AstNode *ast_parse_block_expr(ParseContext *pc) {
1186 TokenIndex label = ast_parse_block_label(pc);
1187 if (label != 0) {
1188 AstNode *res = ast_expect(pc, ast_parse_block);
1189 assert(res->type == NodeTypeBlock);
1190 res->data.block.name = token_buf(pc, label);
1191 return res;
1192 }
1193
1194 return ast_parse_block(pc);
1195}
1196
1197// AssignExpr <- Expr (AssignOp Expr)?
1198static AstNode *ast_parse_assign_expr(ParseContext *pc) {
1199 return ast_parse_bin_op_expr(pc, BinOpChainOnce, ast_parse_assign_op, ast_parse_expr);
1200}
1201
1202// Expr <- KEYWORD_try* BoolOrExpr
1203static AstNode *ast_parse_expr(ParseContext *pc) {
1204 return ast_parse_prefix_op_expr(
1205 pc,
1206 [](ParseContext *context) {
1207 TokenIndex try_token = eat_token_if(context, TokenIdKeywordTry);
1208 if (try_token != 0) {
1209 AstNode *res = ast_create_node(context, NodeTypeReturnExpr, try_token);
1210 res->data.return_expr.kind = ReturnKindError;
1211 return res;
1212 }
1213
1214 return (AstNode*)nullptr;
1215 },
1216 ast_parse_bool_or_expr
1217 );
1218}
1219
1220// BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)*
1221static AstNode *ast_parse_bool_or_expr(ParseContext *pc) {
1222 return ast_parse_bin_op_expr(
1223 pc,
1224 BinOpChainInf,
1225 ast_parse_bin_op_simple<TokenIdKeywordOr, BinOpTypeBoolOr>,
1226 ast_parse_bool_and_expr
1227 );
1228}
1229
1230// BoolAndExpr <- CompareExpr (KEYWORD_and CompareExpr)*
1231static AstNode *ast_parse_bool_and_expr(ParseContext *pc) {
1232 return ast_parse_bin_op_expr(
1233 pc,
1234 BinOpChainInf,
1235 ast_parse_bin_op_simple<TokenIdKeywordAnd, BinOpTypeBoolAnd>,
1236 ast_parse_compare_expr
1237 );
1238}
1239
1240// CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)?
1241static AstNode *ast_parse_compare_expr(ParseContext *pc) {
1242 return ast_parse_bin_op_expr(pc, BinOpChainOnce, ast_parse_compare_op, ast_parse_bitwise_expr);
1243}
1244
1245// BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)*
1246static AstNode *ast_parse_bitwise_expr(ParseContext *pc) {
1247 return ast_parse_bin_op_expr(pc, BinOpChainInf, ast_parse_bitwise_op, ast_parse_bit_shift_expr);
1248}
1249
1250// BitShiftExpr <- AdditionExpr (BitShiftOp AdditionExpr)*
1251static AstNode *ast_parse_bit_shift_expr(ParseContext *pc) {
1252 return ast_parse_bin_op_expr(pc, BinOpChainInf, ast_parse_bit_shift_op, ast_parse_addition_expr);
1253}
1254
1255// AdditionExpr <- MultiplyExpr (AdditionOp MultiplyExpr)*
1256static AstNode *ast_parse_addition_expr(ParseContext *pc) {
1257 return ast_parse_bin_op_expr(pc, BinOpChainInf, ast_parse_addition_op, ast_parse_multiply_expr);
1258}
1259
1260// MultiplyExpr <- PrefixExpr (MultiplyOp PrefixExpr)*
1261static AstNode *ast_parse_multiply_expr(ParseContext *pc) {
1262 return ast_parse_bin_op_expr(pc, BinOpChainInf, ast_parse_multiply_op, ast_parse_prefix_expr);
1263}
1264
1265// PrefixExpr <- PrefixOp* PrimaryExpr
1266static AstNode *ast_parse_prefix_expr(ParseContext *pc) {
1267 return ast_parse_prefix_op_expr(
1268 pc,
1269 ast_parse_prefix_op,
1270 ast_parse_primary_expr
1271 );
1272}
1273
1274// PrimaryExpr
1275// <- AsmExpr
1276// / IfExpr
1277// / KEYWORD_break BreakLabel? Expr?
1278// / KEYWORD_comptime Expr
1279// / KEYWORD_nosuspend Expr
1280// / KEYWORD_continue BreakLabel?
1281// / KEYWORD_resume Expr
1282// / KEYWORD_return Expr?
1283// / BlockLabel? LoopExpr
1284// / Block
1285// / CurlySuffixExpr
1286static AstNode *ast_parse_primary_expr(ParseContext *pc) {
1287 AstNode *asm_expr = ast_parse_asm_expr(pc);
1288 if (asm_expr != nullptr)
1289 return asm_expr;
1290
1291 AstNode *if_expr = ast_parse_if_expr(pc);
1292 if (if_expr != nullptr)
1293 return if_expr;
1294
1295 TokenIndex break_token = eat_token_if(pc, TokenIdKeywordBreak);
1296 if (break_token != 0) {
1297 TokenIndex label = ast_parse_break_label(pc);
1298 AstNode *expr = ast_parse_expr(pc);
1299
1300 AstNode *res = ast_create_node(pc, NodeTypeBreak, break_token);
1301 res->data.break_expr.name = token_buf(pc, label);
1302 res->data.break_expr.expr = expr;
1303 return res;
1304 }
1305
1306 TokenIndex comptime = eat_token_if(pc, TokenIdKeywordCompTime);
1307 if (comptime != 0) {
1308 AstNode *expr = ast_expect(pc, ast_parse_expr);
1309 AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime);
1310 res->data.comptime_expr.expr = expr;
1311 return res;
1312 }
1313
1314 TokenIndex nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend);
1315 if (nosuspend != 0) {
1316 AstNode *expr = ast_expect(pc, ast_parse_expr);
1317 AstNode *res = ast_create_node(pc, NodeTypeNoSuspend, nosuspend);
1318 res->data.nosuspend_expr.expr = expr;
1319 return res;
1320 }
1321
1322 TokenIndex continue_token = eat_token_if(pc, TokenIdKeywordContinue);
1323 if (continue_token != 0) {
1324 TokenIndex label = ast_parse_break_label(pc);
1325 AstNode *res = ast_create_node(pc, NodeTypeContinue, continue_token);
1326 res->data.continue_expr.name = token_buf(pc, label);
1327 return res;
1328 }
1329
1330 TokenIndex resume = eat_token_if(pc, TokenIdKeywordResume);
1331 if (resume != 0) {
1332 AstNode *expr = ast_expect(pc, ast_parse_expr);
1333 AstNode *res = ast_create_node(pc, NodeTypeResume, resume);
1334 res->data.resume_expr.expr = expr;
1335 return res;
1336 }
1337
1338 TokenIndex return_token = eat_token_if(pc, TokenIdKeywordReturn);
1339 if (return_token != 0) {
1340 AstNode *expr = ast_parse_expr(pc);
1341 AstNode *res = ast_create_node(pc, NodeTypeReturnExpr, return_token);
1342 res->data.return_expr.expr = expr;
1343 return res;
1344 }
1345
1346 TokenIndex label = ast_parse_block_label(pc);
1347 AstNode *loop = ast_parse_loop_expr(pc);
1348 if (loop != nullptr) {
1349 switch (loop->type) {
1350 case NodeTypeForExpr:
1351 loop->data.for_expr.name = token_buf(pc, label);
1352 break;
1353 case NodeTypeWhileExpr:
1354 loop->data.while_expr.name = token_buf(pc, label);
1355 break;
1356 default:
1357 zig_unreachable();
1358 }
1359 return loop;
1360 } else if (label != 0) {
1361 // Restore the tokens that we eaten by ast_parse_block_label.
1362 put_back_token(pc);
1363 put_back_token(pc);
1364 }
1365
1366 AstNode *block = ast_parse_block(pc);
1367 if (block != nullptr)
1368 return block;
1369
1370 AstNode *curly_suffix = ast_parse_curly_suffix_expr(pc);
1371 if (curly_suffix != nullptr)
1372 return curly_suffix;
1373
1374 return nullptr;
1375}
1376
1377// IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)?
1378static AstNode *ast_parse_if_expr(ParseContext *pc) {
1379 return ast_parse_if_expr_helper(pc, ast_parse_expr);
1380}
1381
1382// Block <- LBRACE Statement* RBRACE
1383static AstNode *ast_parse_block(ParseContext *pc) {
1384 TokenIndex lbrace = eat_token_if(pc, TokenIdLBrace);
1385 if (lbrace == 0)
1386 return nullptr;
1387
1388 ZigList<AstNode *> statements = {};
1389 AstNode *statement;
1390 while ((statement = ast_parse_statement(pc)) != nullptr)
1391 statements.append(statement);
1392
1393 expect_token(pc, TokenIdRBrace);
1394
1395 AstNode *res = ast_create_node(pc, NodeTypeBlock, lbrace);
1396 res->data.block.statements = statements;
1397 return res;
1398}
1399
1400// LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr)
1401static AstNode *ast_parse_loop_expr(ParseContext *pc) {
1402 return ast_parse_loop_expr_helper(
1403 pc,
1404 ast_parse_for_expr,
1405 ast_parse_while_expr
1406 );
1407}
1408
1409// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?
1410static AstNode *ast_parse_for_expr(ParseContext *pc) {
1411 return ast_parse_for_expr_helper(pc, ast_parse_expr);
1412}
1413
1414// WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)?
1415static AstNode *ast_parse_while_expr(ParseContext *pc) {
1416 return ast_parse_while_expr_helper(pc, ast_parse_expr);
1417}
1418
1419// CurlySuffixExpr <- TypeExpr InitList?
1420static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc) {
1421 AstNode *type_expr = ast_parse_type_expr(pc);
1422 if (type_expr == nullptr)
1423 return nullptr;
1424
1425 AstNode *res = ast_parse_init_list(pc);
1426 if (res == nullptr)
1427 return type_expr;
1428
1429 assert(res->type == NodeTypeContainerInitExpr);
1430 res->data.container_init_expr.type = type_expr;
1431 return res;
1432}
1433
1434// InitList
1435// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
1436// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
1437// / LBRACE RBRACE
1438static AstNode *ast_parse_init_list(ParseContext *pc) {
1439 TokenIndex lbrace = eat_token_if(pc, TokenIdLBrace);
1440 if (lbrace == 0)
1441 return nullptr;
1442
1443 AstNode *first = ast_parse_field_init(pc);
1444 if (first != nullptr) {
1445 AstNode *res = ast_create_node(pc, NodeTypeContainerInitExpr, lbrace);
1446 res->data.container_init_expr.kind = ContainerInitKindStruct;
1447 res->data.container_init_expr.entries.append(first);
1448
1449 while (eat_token_if(pc, TokenIdComma) != 0) {
1450 AstNode *field_init = ast_parse_field_init(pc);
1451 if (field_init == nullptr)
1452 break;
1453 res->data.container_init_expr.entries.append(field_init);
1454 }
1455
1456 expect_token(pc, TokenIdRBrace);
1457 return res;
1458 }
1459
1460 AstNode *res = ast_create_node(pc, NodeTypeContainerInitExpr, lbrace);
1461 res->data.container_init_expr.kind = ContainerInitKindArray;
1462
1463 first = ast_parse_expr(pc);
1464 if (first != nullptr) {
1465 res->data.container_init_expr.entries.append(first);
1466
1467 while (eat_token_if(pc, TokenIdComma) != 0) {
1468 AstNode *expr = ast_parse_expr(pc);
1469 if (expr == nullptr)
1470 break;
1471 res->data.container_init_expr.entries.append(expr);
1472 }
1473
1474 expect_token(pc, TokenIdRBrace);
1475 return res;
1476 }
1477
1478 expect_token(pc, TokenIdRBrace);
1479 return res;
1480}
1481
1482// TypeExpr <- PrefixTypeOp* ErrorUnionExpr
1483static AstNode *ast_parse_type_expr(ParseContext *pc) {
1484 return ast_parse_prefix_op_expr(
1485 pc,
1486 ast_parse_prefix_type_op,
1487 ast_parse_error_union_expr
1488 );
1489}
1490
1491// ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
1492static AstNode *ast_parse_error_union_expr(ParseContext *pc) {
1493 AstNode *res = ast_parse_suffix_expr(pc);
1494 if (res == nullptr)
1495 return nullptr;
1496
1497 AstNode *op = ast_parse_bin_op_simple<TokenIdBang, BinOpTypeErrorUnion>(pc);
1498 if (op == nullptr)
1499 return res;
1500
1501 AstNode *right = ast_expect(pc, ast_parse_type_expr);
1502 assert(op->type == NodeTypeBinOpExpr);
1503 op->data.bin_op_expr.op1 = res;
1504 op->data.bin_op_expr.op2 = right;
1505 return op;
1506}
1507
1508// SuffixExpr
1509// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
1510// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
1511static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
1512 TokenIndex async_token = eat_token_if(pc, TokenIdKeywordAsync);
1513 if (async_token) {
1514 AstNode *child = ast_expect(pc, ast_parse_primary_type_expr);
1515 while (true) {
1516 AstNode *suffix = ast_parse_suffix_op(pc);
1517 if (suffix == nullptr)
1518 break;
1519
1520 switch (suffix->type) {
1521 case NodeTypeSliceExpr:
1522 suffix->data.slice_expr.array_ref_expr = child;
1523 break;
1524 case NodeTypeArrayAccessExpr:
1525 suffix->data.array_access_expr.array_ref_expr = child;
1526 break;
1527 case NodeTypeFieldAccessExpr:
1528 suffix->data.field_access_expr.struct_expr = child;
1529 break;
1530 case NodeTypeUnwrapOptional:
1531 suffix->data.unwrap_optional.expr = child;
1532 break;
1533 case NodeTypePtrDeref:
1534 suffix->data.ptr_deref_expr.target = child;
1535 break;
1536 default:
1537 zig_unreachable();
1538 }
1539 child = suffix;
1540 }
1541
1542 // TODO: Both *_async_prefix and *_fn_call_arguments returns an
1543 // AstNode *. All we really want here is the arguments of
1544 // the call we parse. We therefor "leak" the node for now.
1545 // Wait till we get async rework to fix this.
1546 AstNode *args = ast_parse_fn_call_arguments(pc);
1547 if (args == nullptr)
1548 ast_invalid_token_error(pc, peek_token(pc));
1549
1550 assert(args->type == NodeTypeFnCallExpr);
1551
1552 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async_token);
1553 res->data.fn_call_expr.modifier = CallModifierAsync;
1554 res->data.fn_call_expr.seen = false;
1555 res->data.fn_call_expr.fn_ref_expr = child;
1556 res->data.fn_call_expr.params = args->data.fn_call_expr.params;
1557 return res;
1558 }
1559
1560 AstNode *res = ast_parse_primary_type_expr(pc);
1561 if (res == nullptr)
1562 return nullptr;
1563
1564 while (true) {
1565 AstNode *suffix = ast_parse_suffix_op(pc);
1566 if (suffix != nullptr) {
1567 switch (suffix->type) {
1568 case NodeTypeSliceExpr:
1569 suffix->data.slice_expr.array_ref_expr = res;
1570 break;
1571 case NodeTypeArrayAccessExpr:
1572 suffix->data.array_access_expr.array_ref_expr = res;
1573 break;
1574 case NodeTypeFieldAccessExpr:
1575 suffix->data.field_access_expr.struct_expr = res;
1576 break;
1577 case NodeTypeUnwrapOptional:
1578 suffix->data.unwrap_optional.expr = res;
1579 break;
1580 case NodeTypePtrDeref:
1581 suffix->data.ptr_deref_expr.target = res;
1582 break;
1583 default:
1584 zig_unreachable();
1585 }
1586 res = suffix;
1587 continue;
1588 }
1589
1590 AstNode * call = ast_parse_fn_call_arguments(pc);
1591 if (call != nullptr) {
1592 assert(call->type == NodeTypeFnCallExpr);
1593 call->data.fn_call_expr.fn_ref_expr = res;
1594 res = call;
1595 continue;
1596 }
1597
1598 break;
1599 }
1600
1601 return res;
1602
1603}
1604
1605// PrimaryTypeExpr
1606// <- BUILTINIDENTIFIER FnCallArguments
1607// / CHAR_LITERAL
1608// / ContainerDecl
1609// / DOT IDENTIFIER
1610// / ErrorSetDecl
1611// / FLOAT
1612// / FnProto
1613// / GroupedExpr
1614// / LabeledTypeExpr
1615// / IDENTIFIER
1616// / IfTypeExpr
1617// / INTEGER
1618// / KEYWORD_comptime TypeExpr
1619// / KEYWORD_error DOT IDENTIFIER
1620// / KEYWORD_promise
1621// / KEYWORD_unreachable
1622// / STRINGLITERAL
1623// / SwitchExpr
1624static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
1625 TokenIndex builtin_tok = eat_token_if(pc, TokenIdBuiltin);
1626 if (builtin_tok != 0) {
1627 AstNode *res = ast_expect(pc, ast_parse_fn_call_arguments);
1628 AstNode *name_sym = ast_create_node(pc, NodeTypeIdentifier, builtin_tok);
1629
1630 assert(res->type == NodeTypeFnCallExpr);
1631 res->main_token = builtin_tok;
1632 res->data.fn_call_expr.fn_ref_expr = name_sym;
1633 res->data.fn_call_expr.modifier = CallModifierBuiltin;
1634 return res;
1635 }
1636
1637 TokenIndex char_lit = eat_token_if(pc, TokenIdCharLiteral);
1638 if (char_lit != 0) {
1639 return ast_create_node(pc, NodeTypeCharLiteral, char_lit);
1640 }
1641
1642 AstNode *container_decl = ast_parse_container_decl(pc);
1643 if (container_decl != nullptr)
1644 return container_decl;
1645
1646 AstNode *anon_lit = ast_parse_anon_lit(pc);
1647 if (anon_lit != nullptr)
1648 return anon_lit;
1649
1650 AstNode *error_set_decl = ast_parse_error_set_decl(pc);
1651 if (error_set_decl != nullptr)
1652 return error_set_decl;
1653
1654 TokenIndex float_lit = eat_token_if(pc, TokenIdFloatLiteral);
1655 if (float_lit != 0) {
1656 return ast_create_node(pc, NodeTypeFloatLiteral, float_lit);
1657 }
1658
1659 AstNode *fn_proto = ast_parse_fn_proto(pc);
1660 if (fn_proto != nullptr)
1661 return fn_proto;
1662
1663 AstNode *grouped_expr = ast_parse_grouped_expr(pc);
1664 if (grouped_expr != nullptr)
1665 return grouped_expr;
1666
1667 AstNode *labeled_type_expr = ast_parse_labeled_type_expr(pc);
1668 if (labeled_type_expr != nullptr)
1669 return labeled_type_expr;
1670
1671 TokenIndex identifier = eat_token_if(pc, TokenIdIdentifier);
1672 if (identifier != 0)
1673 return token_identifier(pc, identifier);
1674
1675 AstNode *if_type_expr = ast_parse_if_type_expr(pc);
1676 if (if_type_expr != nullptr)
1677 return if_type_expr;
1678
1679 TokenIndex int_lit = eat_token_if(pc, TokenIdIntLiteral);
1680 if (int_lit != 0) {
1681 return ast_create_node(pc, NodeTypeIntLiteral, int_lit);
1682 }
1683
1684 TokenIndex comptime = eat_token_if(pc, TokenIdKeywordCompTime);
1685 if (comptime != 0) {
1686 AstNode *expr = ast_expect(pc, ast_parse_type_expr);
1687 AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime);
1688 res->data.comptime_expr.expr = expr;
1689 return res;
1690 }
1691
1692 TokenIndex error = eat_token_if(pc, TokenIdKeywordError);
1693 if (error != 0) {
1694 TokenIndex dot = expect_token(pc, TokenIdDot);
1695 TokenIndex name = expect_token(pc, TokenIdIdentifier);
1696 AstNode *left = ast_create_node(pc, NodeTypeErrorType, error);
1697 AstNode *res = ast_create_node(pc, NodeTypeFieldAccessExpr, dot);
1698 res->data.field_access_expr.struct_expr = left;
1699 res->data.field_access_expr.field_name = token_buf(pc, name);
1700 return res;
1701 }
1702
1703 TokenIndex anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame);
1704 if (anyframe != 0)
1705 return ast_create_node(pc, NodeTypeAnyFrameType, anyframe);
1706
1707 TokenIndex unreachable = eat_token_if(pc, TokenIdKeywordUnreachable);
1708 if (unreachable != 0)
1709 return ast_create_node(pc, NodeTypeUnreachable, unreachable);
1710
1711
1712 TokenIndex string_lit = eat_token_if(pc, TokenIdStringLiteral);
1713 if (string_lit != 0) {
1714 return ast_create_node(pc, NodeTypeStringLiteral, string_lit);
1715 }
1716
1717 TokenIndex multiline_str_lit = ast_parse_multi_tok(pc, TokenIdMultilineStringLiteralLine);
1718 if (multiline_str_lit != 0) {
1719 return ast_create_node(pc, NodeTypeStringLiteral, multiline_str_lit);
1720 }
1721
1722 AstNode *switch_expr = ast_parse_switch_expr(pc);
1723 if (switch_expr != nullptr)
1724 return switch_expr;
1725
1726 return nullptr;
1727}
1728
1729// ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto
1730static AstNode *ast_parse_container_decl(ParseContext *pc) {
1731 TokenIndex layout_token = eat_token_if(pc, TokenIdKeywordExtern);
1732 if (layout_token == 0)
1733 layout_token = eat_token_if(pc, TokenIdKeywordPacked);
1734
1735 AstNode *res = ast_parse_container_decl_auto(pc);
1736 if (res == nullptr) {
1737 if (layout_token != 0)
1738 put_back_token(pc);
1739 return nullptr;
1740 }
1741
1742 assert(res->type == NodeTypeContainerDecl);
1743 if (layout_token != 0) {
1744 res->main_token = layout_token;
1745 res->data.container_decl.layout = pc->token_ids[layout_token] == TokenIdKeywordExtern
1746 ? ContainerLayoutExtern
1747 : ContainerLayoutPacked;
1748 }
1749 return res;
1750}
1751
1752// ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE
1753static AstNode *ast_parse_error_set_decl(ParseContext *pc) {
1754 TokenIndex first = eat_token_if(pc, TokenIdKeywordError);
1755 if (first == 0)
1756 return nullptr;
1757 if (eat_token_if(pc, TokenIdLBrace) == 0) {
1758 put_back_token(pc);
1759 return nullptr;
1760 }
1761
1762 ZigList<AstNode *> decls = ast_parse_list<AstNode>(pc, TokenIdComma, [](ParseContext *context) {
1763 TokenIndex doc_token = ast_parse_doc_comments(context);
1764 TokenIndex ident = eat_token_if(context, TokenIdIdentifier);
1765 if (ident == 0)
1766 return (AstNode*)nullptr;
1767
1768 AstNode *symbol_node = token_identifier(context, ident);
1769 if (doc_token == 0)
1770 return symbol_node;
1771
1772 AstNode *field_node = ast_create_node(context, NodeTypeErrorSetField, doc_token);
1773 field_node->data.err_set_field.field_name = symbol_node;
1774 field_node->data.err_set_field.doc_comments = doc_token;
1775 return field_node;
1776 });
1777 expect_token(pc, TokenIdRBrace);
1778
1779 AstNode *res = ast_create_node(pc, NodeTypeErrorSetDecl, first);
1780 res->data.err_set_decl.decls = decls;
1781 return res;
1782}
1783
1784// GroupedExpr <- LPAREN Expr RPAREN
1785static AstNode *ast_parse_grouped_expr(ParseContext *pc) {
1786 TokenIndex lparen = eat_token_if(pc, TokenIdLParen);
1787 if (lparen == 0)
1788 return nullptr;
1789
1790 AstNode *expr = ast_expect(pc, ast_parse_expr);
1791 expect_token(pc, TokenIdRParen);
1792
1793 AstNode *res = ast_create_node(pc, NodeTypeGroupedExpr, lparen);
1794 res->data.grouped_expr = expr;
1795 return res;
1796}
1797
1798// IfTypeExpr <- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
1799static AstNode *ast_parse_if_type_expr(ParseContext *pc) {
1800 return ast_parse_if_expr_helper(pc, ast_parse_type_expr);
1801}
1802
1803// LabeledTypeExpr
1804// <- BlockLabel Block
1805// / BlockLabel? LoopTypeExpr
1806static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) {
1807 TokenIndex label = ast_parse_block_label(pc);
1808 if (label != 0) {
1809 AstNode *block = ast_parse_block(pc);
1810 if (block != nullptr) {
1811 assert(block->type == NodeTypeBlock);
1812 block->data.block.name = token_buf(pc, label);
1813 return block;
1814 }
1815 }
1816
1817 AstNode *loop = ast_parse_loop_type_expr(pc);
1818 if (loop != nullptr) {
1819 switch (loop->type) {
1820 case NodeTypeForExpr:
1821 loop->data.for_expr.name = token_buf(pc, label);
1822 break;
1823 case NodeTypeWhileExpr:
1824 loop->data.while_expr.name = token_buf(pc, label);
1825 break;
1826 default:
1827 zig_unreachable();
1828 }
1829 return loop;
1830 }
1831
1832 if (label != 0) {
1833 put_back_token(pc);
1834 put_back_token(pc);
1835 }
1836 return nullptr;
1837}
1838
1839// LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr)
1840static AstNode *ast_parse_loop_type_expr(ParseContext *pc) {
1841 return ast_parse_loop_expr_helper(
1842 pc,
1843 ast_parse_for_type_expr,
1844 ast_parse_while_type_expr
1845 );
1846}
1847
1848// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?
1849static AstNode *ast_parse_for_type_expr(ParseContext *pc) {
1850 return ast_parse_for_expr_helper(pc, ast_parse_type_expr);
1851}
1852
1853// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
1854static AstNode *ast_parse_while_type_expr(ParseContext *pc) {
1855 return ast_parse_while_expr_helper(pc, ast_parse_type_expr);
1856}
1857
1858// SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE
1859static AstNode *ast_parse_switch_expr(ParseContext *pc) {
1860 TokenIndex switch_token = eat_token_if(pc, TokenIdKeywordSwitch);
1861 if (switch_token == 0)
1862 return nullptr;
1863
1864 expect_token(pc, TokenIdLParen);
1865 AstNode *expr = ast_expect(pc, ast_parse_expr);
1866 expect_token(pc, TokenIdRParen);
1867 expect_token(pc, TokenIdLBrace);
1868 ZigList<AstNode *> prongs = ast_parse_list(pc, TokenIdComma, ast_parse_switch_prong);
1869 expect_token(pc, TokenIdRBrace);
1870
1871 AstNode *res = ast_create_node(pc, NodeTypeSwitchExpr, switch_token);
1872 res->data.switch_expr.expr = expr;
1873 res->data.switch_expr.prongs = prongs;
1874 return res;
1875}
1876
1877// AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN STRINGLITERAL AsmOutput? RPAREN
1878static AstNode *ast_parse_asm_expr(ParseContext *pc) {
1879 TokenIndex asm_token = eat_token_if(pc, TokenIdKeywordAsm);
1880 if (asm_token == 0)
1881 return nullptr;
1882
1883 TokenIndex volatile_token = eat_token_if(pc, TokenIdKeywordVolatile);
1884 expect_token(pc, TokenIdLParen);
1885 AstNode *asm_template = ast_expect(pc, ast_parse_expr);
1886 AstNode *res = ast_parse_asm_output(pc);
1887 if (res == nullptr)
1888 res = ast_create_node_no_line_info(pc, NodeTypeAsmExpr);
1889 expect_token(pc, TokenIdRParen);
1890
1891 res->main_token = asm_token;
1892 res->data.asm_expr.volatile_token = volatile_token;
1893 res->data.asm_expr.asm_template = asm_template;
1894 return res;
1895}
1896
1897static AstNode *ast_parse_anon_lit(ParseContext *pc) {
1898 TokenIndex period = eat_token_if(pc, TokenIdDot);
1899 if (period == 0)
1900 return nullptr;
1901
1902 // anon enum literal
1903 TokenIndex identifier = eat_token_if(pc, TokenIdIdentifier);
1904 if (identifier != 0) {
1905 return ast_create_node(pc, NodeTypeEnumLiteral, period);
1906 }
1907
1908 // anon container literal
1909 AstNode *res = ast_parse_init_list(pc);
1910 if (res != nullptr)
1911 return res;
1912 put_back_token(pc);
1913 return nullptr;
1914}
1915
1916// AsmOutput <- COLON AsmOutputList AsmInput?
1917static AstNode *ast_parse_asm_output(ParseContext *pc) {
1918 if (eat_token_if(pc, TokenIdColon) == 0)
1919 return nullptr;
1920
1921 ZigList<AsmOutput *> output_list = ast_parse_list(pc, TokenIdComma, ast_parse_asm_output_item);
1922 AstNode *res = ast_parse_asm_input(pc);
1923 if (res == nullptr)
1924 res = ast_create_node_no_line_info(pc, NodeTypeAsmExpr);
1925
1926 res->data.asm_expr.output_list = output_list;
1927 return res;
1928}
1929
1930// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
1931static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
1932 if (eat_token_if(pc, TokenIdLBracket) == 0)
1933 return nullptr;
1934
1935 TokenIndex sym_name = expect_token(pc, TokenIdIdentifier);
1936 expect_token(pc, TokenIdRBracket);
1937
1938 TokenIndex str = ast_parse_multi_tok(pc, TokenIdMultilineStringLiteralLine);
1939 if (str == 0)
1940 str = expect_token(pc, TokenIdStringLiteral);
1941 expect_token(pc, TokenIdLParen);
1942
1943 TokenIndex var_name = eat_token_if(pc, TokenIdIdentifier);
1944 AstNode *return_type = nullptr;
1945 if (var_name == 0) {
1946 expect_token(pc, TokenIdArrow);
1947 return_type = ast_expect(pc, ast_parse_type_expr);
1948 }
1949
1950 expect_token(pc, TokenIdRParen);
1951
1952 AsmOutput *res = heap::c_allocator.create<AsmOutput>();
1953 res->asm_symbolic_name = token_buf(pc, sym_name);
1954 res->constraint = token_buf(pc, str);
1955 res->variable_name = token_buf(pc, var_name);
1956 res->return_type = return_type;
1957 return res;
1958}
1959
1960// AsmInput <- COLON AsmInputList AsmClobbers?
1961static AstNode *ast_parse_asm_input(ParseContext *pc) {
1962 if (eat_token_if(pc, TokenIdColon) == 0)
1963 return nullptr;
1964
1965 ZigList<AsmInput *> input_list = ast_parse_list(pc, TokenIdComma, ast_parse_asm_input_item);
1966 AstNode *res = ast_parse_asm_clobbers(pc);
1967 if (res == nullptr)
1968 res = ast_create_node_no_line_info(pc, NodeTypeAsmExpr);
1969
1970 res->data.asm_expr.input_list = input_list;
1971 return res;
1972}
1973
1974// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
1975static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {
1976 if (eat_token_if(pc, TokenIdLBracket) == 0)
1977 return nullptr;
1978
1979 TokenIndex sym_name = expect_token(pc, TokenIdIdentifier);
1980 expect_token(pc, TokenIdRBracket);
1981
1982 TokenIndex constraint = expect_token(pc, TokenIdStringLiteral);
1983 expect_token(pc, TokenIdLParen);
1984 AstNode *expr = ast_expect(pc, ast_parse_expr);
1985 expect_token(pc, TokenIdRParen);
1986
1987 AsmInput *res = heap::c_allocator.create<AsmInput>();
1988 res->asm_symbolic_name = token_buf(pc, sym_name);
1989 res->constraint = token_buf(pc, constraint);
1990 res->expr = expr;
1991 return res;
1992}
1993
1994// AsmClobbers <- COLON StringList
1995static AstNode *ast_parse_asm_clobbers(ParseContext *pc) {
1996 if (eat_token_if(pc, TokenIdColon) == 0)
1997 return nullptr;
1998
1999 ZigList<Buf *> clobber_list = ast_parse_list<Buf>(pc, TokenIdComma, [](ParseContext *context) {
2000 TokenIndex str = eat_token_if(context, TokenIdStringLiteral);
2001 if (str == 0)
2002 str = ast_parse_multi_tok(context, TokenIdMultilineStringLiteralLine);
2003 if (str != 0)
2004 return token_buf(context, str);
2005 return (Buf*)nullptr;
2006 });
2007
2008 AstNode *res = ast_create_node_no_line_info(pc, NodeTypeAsmExpr);
2009 res->data.asm_expr.clobber_list = clobber_list;
2010 return res;
2011}
2012
2013// BreakLabel <- COLON IDENTIFIER
2014static TokenIndex ast_parse_break_label(ParseContext *pc) {
2015 if (eat_token_if(pc, TokenIdColon) == 0)
2016 return 0;
2017
2018 return expect_token(pc, TokenIdIdentifier);
2019}
2020
2021// BlockLabel <- IDENTIFIER COLON
2022static TokenIndex ast_parse_block_label(ParseContext *pc) {
2023 TokenIndex ident = eat_token_if(pc, TokenIdIdentifier);
2024 if (ident == 0)
2025 return 0;
2026
2027 // We do 2 token lookahead here, as we don't want to error when
2028 // parsing identifiers.
2029 if (eat_token_if(pc, TokenIdColon) == 0) {
2030 put_back_token(pc);
2031 return 0;
2032 }
2033
2034 return ident;
2035}
2036
2037// FieldInit <- DOT IDENTIFIER EQUAL Expr
2038static AstNode *ast_parse_field_init(ParseContext *pc) {
2039 TokenIndex first = eat_token_if(pc, TokenIdDot);
2040 if (first == 0)
2041 return nullptr;
2042
2043 TokenIndex name = eat_token_if(pc, TokenIdIdentifier);
2044 if (name == 0) {
2045 // Because of anon literals ".{" is also valid.
2046 put_back_token(pc);
2047 return nullptr;
2048 }
2049 if (eat_token_if(pc, TokenIdEq) == 0) {
2050 // Because ".Name" can also be interpreted as an enum literal, we should put back
2051 // those two tokens again so that the parser can try to parse them as the enum
2052 // literal later.
2053 put_back_token(pc);
2054 put_back_token(pc);
2055 return nullptr;
2056 }
2057 AstNode *expr = ast_expect(pc, ast_parse_expr);
2058
2059 AstNode *res = ast_create_node(pc, NodeTypeStructValueField, first);
2060 res->data.struct_val_field.name = token_buf(pc, name);
2061 res->data.struct_val_field.expr = expr;
2062 return res;
2063}
2064
2065// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
2066static AstNode *ast_parse_while_continue_expr(ParseContext *pc) {
2067 TokenIndex first = eat_token_if(pc, TokenIdColon);
2068 if (first == 0)
2069 return nullptr;
2070
2071 expect_token(pc, TokenIdLParen);
2072 AstNode *expr = ast_expect(pc, ast_parse_assign_expr);
2073 expect_token(pc, TokenIdRParen);
2074 return expr;
2075}
2076
2077// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
2078static AstNode *ast_parse_link_section(ParseContext *pc) {
2079 TokenIndex first = eat_token_if(pc, TokenIdKeywordLinkSection);
2080 if (first == 0)
2081 return nullptr;
2082
2083 expect_token(pc, TokenIdLParen);
2084 AstNode *res = ast_expect(pc, ast_parse_expr);
2085 expect_token(pc, TokenIdRParen);
2086 return res;
2087}
2088
2089// CallConv <- KEYWORD_callconv LPAREN Expr RPAREN
2090static AstNode *ast_parse_callconv(ParseContext *pc) {
2091 TokenIndex first = eat_token_if(pc, TokenIdKeywordCallconv);
2092 if (first == 0)
2093 return nullptr;
2094
2095 expect_token(pc, TokenIdLParen);
2096 AstNode *res = ast_expect(pc, ast_parse_expr);
2097 expect_token(pc, TokenIdRParen);
2098 return res;
2099}
2100
2101// ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
2102static AstNode *ast_parse_param_decl(ParseContext *pc) {
2103 TokenIndex first_doc_comment = ast_parse_doc_comments(pc);
2104
2105 TokenIndex first = eat_token_if(pc, TokenIdKeywordNoAlias);
2106 if (first == 0)
2107 first = eat_token_if(pc, TokenIdKeywordCompTime);
2108
2109 TokenIndex name = eat_token_if(pc, TokenIdIdentifier);
2110 if (name != 0) {
2111 if (eat_token_if(pc, TokenIdColon) != 0) {
2112 if (first == 0)
2113 first = name;
2114 } else {
2115 // We put back the ident, so it can be parsed as a ParamType
2116 // later.
2117 put_back_token(pc);
2118 name = 0;
2119 }
2120 }
2121
2122 AstNode *res;
2123 if (first == 0) {
2124 first = peek_token(pc);
2125 res = ast_parse_param_type(pc);
2126 } else {
2127 res = ast_expect(pc, ast_parse_param_type);
2128 }
2129
2130 if (res == nullptr)
2131 return nullptr;
2132
2133 assert(res->type == NodeTypeParamDecl);
2134 res->main_token = first;
2135 res->data.param_decl.name = token_buf(pc, name);
2136 res->data.param_decl.doc_comments = first_doc_comment;
2137 res->data.param_decl.is_noalias = pc->token_ids[first] == TokenIdKeywordNoAlias;
2138 res->data.param_decl.is_comptime = pc->token_ids[first] == TokenIdKeywordCompTime;
2139 return res;
2140}
2141
2142// ParamType
2143// <- KEYWORD_anytype
2144// / DOT3
2145// / TypeExpr
2146static AstNode *ast_parse_param_type(ParseContext *pc) {
2147 TokenIndex anytype_token = eat_token_if(pc, TokenIdKeywordAnyType);
2148 if (anytype_token != 0) {
2149 AstNode *res = ast_create_node(pc, NodeTypeParamDecl, anytype_token);
2150 res->data.param_decl.anytype_token = anytype_token;
2151 return res;
2152 }
2153
2154 TokenIndex dots = eat_token_if(pc, TokenIdEllipsis3);
2155 if (dots != 0) {
2156 AstNode *res = ast_create_node(pc, NodeTypeParamDecl, dots);
2157 res->data.param_decl.is_var_args = true;
2158 return res;
2159 }
2160
2161 AstNode *type_expr = ast_parse_type_expr(pc);
2162 if (type_expr != nullptr) {
2163 AstNode *res = ast_create_node_copy_line_info(pc, NodeTypeParamDecl, type_expr);
2164 res->data.param_decl.type = type_expr;
2165 return res;
2166 }
2167
2168 return nullptr;
2169}
2170
2171// IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload?
2172static AstNode *ast_parse_if_prefix(ParseContext *pc) {
2173 TokenIndex first = eat_token_if(pc, TokenIdKeywordIf);
2174 if (first == 0)
2175 return nullptr;
2176
2177 expect_token(pc, TokenIdLParen);
2178 AstNode *condition = ast_expect(pc, ast_parse_expr);
2179 expect_token(pc, TokenIdRParen);
2180 Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);
2181
2182 PtrPayload payload;
2183 AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first);
2184 res->data.test_expr.target_node = condition;
2185 if (opt_payload.unwrap(&payload)) {
2186 res->data.test_expr.var_symbol = token_buf(pc, payload.payload);
2187 res->data.test_expr.var_is_ptr = payload.asterisk != 0;
2188 }
2189 return res;
2190}
2191
2192// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
2193static AstNode *ast_parse_while_prefix(ParseContext *pc) {
2194 TokenIndex while_token = eat_token_if(pc, TokenIdKeywordWhile);
2195 if (while_token == 0)
2196 return nullptr;
2197
2198 expect_token(pc, TokenIdLParen);
2199 AstNode *condition = ast_expect(pc, ast_parse_expr);
2200 expect_token(pc, TokenIdRParen);
2201 Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);
2202 AstNode *continue_expr = ast_parse_while_continue_expr(pc);
2203
2204 PtrPayload payload;
2205 AstNode *res = ast_create_node(pc, NodeTypeWhileExpr, while_token);
2206 res->data.while_expr.condition = condition;
2207 res->data.while_expr.continue_expr = continue_expr;
2208 if (opt_payload.unwrap(&payload)) {
2209 res->data.while_expr.var_symbol = token_buf(pc, payload.payload);
2210 res->data.while_expr.var_is_ptr = payload.asterisk != 0;
2211 }
2212
2213 return res;
2214}
2215
2216// ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload
2217static AstNode *ast_parse_for_prefix(ParseContext *pc) {
2218 TokenIndex for_token = eat_token_if(pc, TokenIdKeywordFor);
2219 if (for_token == 0)
2220 return nullptr;
2221
2222 expect_token(pc, TokenIdLParen);
2223 AstNode *array_expr = ast_expect(pc, ast_parse_expr);
2224 expect_token(pc, TokenIdRParen);
2225 PtrIndexPayload payload;
2226 if (!ast_parse_ptr_index_payload(pc).unwrap(&payload))
2227 ast_invalid_token_error(pc, peek_token(pc));
2228
2229 AstNode *res = ast_create_node(pc, NodeTypeForExpr, for_token);
2230 res->data.for_expr.array_expr = array_expr;
2231 res->data.for_expr.elem_node = token_identifier(pc, payload.payload);
2232 res->data.for_expr.elem_is_ptr = payload.asterisk != 0;
2233 if (payload.index != 0)
2234 res->data.for_expr.index_node = token_identifier(pc, payload.index);
2235
2236 return res;
2237}
2238
2239// Payload <- PIPE IDENTIFIER PIPE
2240static TokenIndex ast_parse_payload(ParseContext *pc) {
2241 if (eat_token_if(pc, TokenIdBinOr) == 0)
2242 return 0;
2243
2244 TokenIndex res = expect_token(pc, TokenIdIdentifier);
2245 expect_token(pc, TokenIdBinOr);
2246 return res;
2247}
2248
2249// PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE
2250static Optional<PtrPayload> ast_parse_ptr_payload(ParseContext *pc) {
2251 if (eat_token_if(pc, TokenIdBinOr) == 0)
2252 return Optional<PtrPayload>::none();
2253
2254 TokenIndex asterisk = eat_token_if(pc, TokenIdStar);
2255 TokenIndex payload = expect_token(pc, TokenIdIdentifier);
2256 expect_token(pc, TokenIdBinOr);
2257
2258 PtrPayload res;
2259 res.asterisk = asterisk;
2260 res.payload = payload;
2261 return Optional<PtrPayload>::some(res);
2262}
2263
2264// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
2265static Optional<PtrIndexPayload> ast_parse_ptr_index_payload(ParseContext *pc) {
2266 if (eat_token_if(pc, TokenIdBinOr) == 0)
2267 return Optional<PtrIndexPayload>::none();
2268
2269 TokenIndex asterisk = eat_token_if(pc, TokenIdStar);
2270 TokenIndex payload = expect_token(pc, TokenIdIdentifier);
2271 TokenIndex index = 0;
2272 if (eat_token_if(pc, TokenIdComma) != 0)
2273 index = expect_token(pc, TokenIdIdentifier);
2274 expect_token(pc, TokenIdBinOr);
2275
2276 PtrIndexPayload res;
2277 res.asterisk = asterisk;
2278 res.payload = payload;
2279 res.index = index;
2280 return Optional<PtrIndexPayload>::some(res);
2281}
2282
2283// SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? AssignExpr
2284static AstNode *ast_parse_switch_prong(ParseContext *pc) {
2285 AstNode *res = ast_parse_switch_case(pc);
2286 if (res == nullptr)
2287 return nullptr;
2288
2289 expect_token(pc, TokenIdFatArrow);
2290 Optional<PtrIndexPayload> opt_payload = ast_parse_ptr_index_payload(pc);
2291 AstNode *expr = ast_expect(pc, ast_parse_assign_expr);
2292
2293 PtrIndexPayload payload;
2294 assert(res->type == NodeTypeSwitchProng);
2295 res->data.switch_prong.expr = expr;
2296 if (opt_payload.unwrap(&payload)) {
2297 res->data.switch_prong.var_symbol = token_identifier(pc, payload.payload);
2298 res->data.switch_prong.var_is_ptr = payload.asterisk != 0;
2299 }
2300
2301 return res;
2302}
2303
2304// SwitchCase
2305// <- SwitchItem (COMMA SwitchItem)* COMMA?
2306// / KEYWORD_else
2307static AstNode *ast_parse_switch_case(ParseContext *pc) {
2308 bool is_inline = eat_token_if(pc, TokenIdKeywordInline) != 0;
2309 AstNode *first = ast_parse_switch_item(pc);
2310 if (first != nullptr) {
2311 AstNode *res = ast_create_node_copy_line_info(pc, NodeTypeSwitchProng, first);
2312 res->data.switch_prong.is_inline = is_inline;
2313 res->data.switch_prong.items.append(first);
2314 res->data.switch_prong.any_items_are_range = first->type == NodeTypeSwitchRange;
2315
2316 while (eat_token_if(pc, TokenIdComma) != 0) {
2317 AstNode *item = ast_parse_switch_item(pc);
2318 if (item == nullptr)
2319 break;
2320
2321 res->data.switch_prong.items.append(item);
2322 res->data.switch_prong.any_items_are_range |= item->type == NodeTypeSwitchRange;
2323 }
2324
2325 return res;
2326 }
2327
2328 TokenIndex else_token = eat_token_if(pc, TokenIdKeywordElse);
2329 if (else_token != 0) {
2330 AstNode *res = ast_create_node(pc, NodeTypeSwitchProng, else_token);
2331 res->data.switch_prong.is_inline = is_inline;
2332 return res;
2333 }
2334
2335 if (is_inline) pc->current_token -= 1;
2336 return nullptr;
2337}
2338
2339// SwitchItem <- Expr (DOT3 Expr)?
2340static AstNode *ast_parse_switch_item(ParseContext *pc) {
2341 AstNode *expr = ast_parse_expr(pc);
2342 if (expr == nullptr)
2343 return nullptr;
2344
2345 TokenIndex dots = eat_token_if(pc, TokenIdEllipsis3);
2346 if (dots != 0) {
2347 AstNode *expr2 = ast_expect(pc, ast_parse_expr);
2348 AstNode *res = ast_create_node(pc, NodeTypeSwitchRange, dots);
2349 res->data.switch_range.start = expr;
2350 res->data.switch_range.end = expr2;
2351 return res;
2352 }
2353
2354 return expr;
2355}
2356
2357// AssignOp
2358// <- ASTERISKEQUAL
2359// / SLASHEQUAL
2360// / PERCENTEQUAL
2361// / PLUSEQUAL
2362// / MINUSEQUAL
2363// / LARROW2EQUAL
2364// / LARROW2PIPEEQUAL
2365// / RARROW2EQUAL
2366// / AMPERSANDEQUAL
2367// / CARETEQUAL
2368// / PIPEEQUAL
2369// / ASTERISKPERCENTEQUAL
2370// / PLUSPERCENTEQUAL
2371// / MINUSPERCENTEQUAL
2372// / ASTERISKPIPEEQUAL
2373// / PLUSPIPEEQUAL
2374// / MINUSPIPEEQUAL
2375// / EQUAL
2376static AstNode *ast_parse_assign_op(ParseContext *pc) {
2377 // In C, we have `T arr[N] = {[i] = T{}};` but it doesn't
2378 // seem to work in C++...
2379 BinOpType table[TokenIdCount] = {};
2380 table[TokenIdBitAndEq] = BinOpTypeAssignBitAnd;
2381 table[TokenIdBitOrEq] = BinOpTypeAssignBitOr;
2382 table[TokenIdBitShiftLeftEq] = BinOpTypeAssignBitShiftLeft;
2383 table[TokenIdBitShiftLeftPipeEq] = BinOpTypeAssignBitShiftLeftSat;
2384 table[TokenIdBitShiftRightEq] = BinOpTypeAssignBitShiftRight;
2385 table[TokenIdBitXorEq] = BinOpTypeAssignBitXor;
2386 table[TokenIdDivEq] = BinOpTypeAssignDiv;
2387 table[TokenIdEq] = BinOpTypeAssign;
2388 table[TokenIdMinusEq] = BinOpTypeAssignMinus;
2389 table[TokenIdMinusPercentEq] = BinOpTypeAssignMinusWrap;
2390 table[TokenIdMinusPipeEq] = BinOpTypeAssignMinusSat;
2391 table[TokenIdModEq] = BinOpTypeAssignMod;
2392 table[TokenIdPlusEq] = BinOpTypeAssignPlus;
2393 table[TokenIdPlusPercentEq] = BinOpTypeAssignPlusWrap;
2394 table[TokenIdPlusPipeEq] = BinOpTypeAssignPlusSat;
2395 table[TokenIdTimesEq] = BinOpTypeAssignTimes;
2396 table[TokenIdTimesPercentEq] = BinOpTypeAssignTimesWrap;
2397 table[TokenIdTimesPipeEq] = BinOpTypeAssignTimesSat;
2398
2399 BinOpType op = table[pc->token_ids[pc->current_token]];
2400 if (op != BinOpTypeInvalid) {
2401 TokenIndex op_token = eat_token(pc);
2402 AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
2403 res->data.bin_op_expr.bin_op = op;
2404 return res;
2405 }
2406
2407 return nullptr;
2408
2409}
2410
2411// CompareOp
2412// <- EQUALEQUAL
2413// / EXCLAMATIONMARKEQUAL
2414// / LARROW
2415// / RARROW
2416// / LARROWEQUAL
2417// / RARROWEQUAL
2418static AstNode *ast_parse_compare_op(ParseContext *pc) {
2419 BinOpType table[TokenIdCount] = {};
2420 table[TokenIdCmpEq] = BinOpTypeCmpEq;
2421 table[TokenIdCmpNotEq] = BinOpTypeCmpNotEq;
2422 table[TokenIdCmpLessThan] = BinOpTypeCmpLessThan;
2423 table[TokenIdCmpGreaterThan] = BinOpTypeCmpGreaterThan;
2424 table[TokenIdCmpLessOrEq] = BinOpTypeCmpLessOrEq;
2425 table[TokenIdCmpGreaterOrEq] = BinOpTypeCmpGreaterOrEq;
2426
2427 BinOpType op = table[pc->token_ids[pc->current_token]];
2428 if (op != BinOpTypeInvalid) {
2429 TokenIndex op_token = eat_token(pc);
2430 AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
2431 res->data.bin_op_expr.bin_op = op;
2432 return res;
2433 }
2434
2435 return nullptr;
2436}
2437
2438// BitwiseOp
2439// <- AMPERSAND
2440// / CARET
2441// / PIPE
2442// / KEYWORD_orelse
2443// / KEYWORD_catch Payload?
2444static AstNode *ast_parse_bitwise_op(ParseContext *pc) {
2445 BinOpType table[TokenIdCount] = {};
2446 table[TokenIdAmpersand] = BinOpTypeBinAnd;
2447 table[TokenIdBinXor] = BinOpTypeBinXor;
2448 table[TokenIdBinOr] = BinOpTypeBinOr;
2449 table[TokenIdKeywordOrElse] = BinOpTypeUnwrapOptional;
2450
2451 BinOpType op = table[pc->token_ids[pc->current_token]];
2452 if (op != BinOpTypeInvalid) {
2453 TokenIndex op_token = eat_token(pc);
2454 AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
2455 res->data.bin_op_expr.bin_op = op;
2456 return res;
2457 }
2458
2459 TokenIndex catch_token = eat_token_if(pc, TokenIdKeywordCatch);
2460 if (catch_token != 0) {
2461 TokenIndex payload = ast_parse_payload(pc);
2462 AstNode *res = ast_create_node(pc, NodeTypeCatchExpr, catch_token);
2463 if (payload != 0)
2464 res->data.unwrap_err_expr.symbol = token_identifier(pc, payload);
2465
2466 return res;
2467 }
2468
2469 return nullptr;
2470}
2471
2472// BitShiftOp
2473// <- LARROW2
2474// / LARROW2PIPE
2475// / RARROW2
2476static AstNode *ast_parse_bit_shift_op(ParseContext *pc) {
2477 BinOpType table[TokenIdCount] = {};
2478 table[TokenIdBitShiftLeft] = BinOpTypeBitShiftLeft;
2479 table[TokenIdBitShiftLeftPipe] = BinOpTypeBitShiftLeftSat;
2480 table[TokenIdBitShiftRight] = BinOpTypeBitShiftRight;
2481
2482 BinOpType op = table[pc->token_ids[pc->current_token]];
2483 if (op != BinOpTypeInvalid) {
2484 TokenIndex op_token = eat_token(pc);
2485 AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
2486 res->data.bin_op_expr.bin_op = op;
2487 return res;
2488 }
2489
2490 return nullptr;
2491}
2492
2493// AdditionOp
2494// <- PLUS
2495// / MINUS
2496// / PLUS2
2497// / PLUSPERCENT
2498// / MINUSPERCENT
2499// / PLUSPIPE
2500// / MINUSPIPE
2501static AstNode *ast_parse_addition_op(ParseContext *pc) {
2502 BinOpType table[TokenIdCount] = {};
2503 table[TokenIdPlus] = BinOpTypeAdd;
2504 table[TokenIdDash] = BinOpTypeSub;
2505 table[TokenIdPlusPlus] = BinOpTypeArrayCat;
2506 table[TokenIdPlusPercent] = BinOpTypeAddWrap;
2507 table[TokenIdMinusPercent] = BinOpTypeSubWrap;
2508 table[TokenIdPlusPipe] = BinOpTypeAddSat;
2509 table[TokenIdMinusPipe] = BinOpTypeSubSat;
2510
2511 BinOpType op = table[pc->token_ids[pc->current_token]];
2512 if (op != BinOpTypeInvalid) {
2513 TokenIndex op_token = eat_token(pc);
2514 AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
2515 res->data.bin_op_expr.bin_op = op;
2516 return res;
2517 }
2518
2519 return nullptr;
2520}
2521
2522// MultiplyOp
2523// <- PIPE2
2524// / ASTERISK
2525// / SLASH
2526// / PERCENT
2527// / ASTERISK2
2528// / ASTERISKPERCENT
2529// / ASTERISKPIPE
2530static AstNode *ast_parse_multiply_op(ParseContext *pc) {
2531 BinOpType table[TokenIdCount] = {};
2532 table[TokenIdBarBar] = BinOpTypeMergeErrorSets;
2533 table[TokenIdStar] = BinOpTypeMult;
2534 table[TokenIdSlash] = BinOpTypeDiv;
2535 table[TokenIdPercent] = BinOpTypeMod;
2536 table[TokenIdStarStar] = BinOpTypeArrayMult;
2537 table[TokenIdTimesPercent] = BinOpTypeMultWrap;
2538 table[TokenIdTimesPipe] = BinOpTypeMultSat;
2539
2540 BinOpType op = table[pc->token_ids[pc->current_token]];
2541 if (op != BinOpTypeInvalid) {
2542 TokenIndex op_token = eat_token(pc);
2543 AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
2544 res->data.bin_op_expr.bin_op = op;
2545 return res;
2546 }
2547
2548 return nullptr;
2549}
2550
2551// PrefixOp
2552// <- EXCLAMATIONMARK
2553// / MINUS
2554// / TILDE
2555// / MINUSPERCENT
2556// / AMPERSAND
2557// / KEYWORD_try
2558// / KEYWORD_await
2559static AstNode *ast_parse_prefix_op(ParseContext *pc) {
2560 PrefixOp table[TokenIdCount] = {};
2561 table[TokenIdBang] = PrefixOpBoolNot;
2562 table[TokenIdDash] = PrefixOpNegation;
2563 table[TokenIdTilde] = PrefixOpBinNot;
2564 table[TokenIdMinusPercent] = PrefixOpNegationWrap;
2565 table[TokenIdAmpersand] = PrefixOpAddrOf;
2566
2567 PrefixOp op = table[pc->token_ids[pc->current_token]];
2568 if (op != PrefixOpInvalid) {
2569 TokenIndex op_token = eat_token(pc);
2570 AstNode *res = ast_create_node(pc, NodeTypePrefixOpExpr, op_token);
2571 res->data.prefix_op_expr.prefix_op = op;
2572 return res;
2573 }
2574
2575 TokenIndex try_token = eat_token_if(pc, TokenIdKeywordTry);
2576 if (try_token != 0) {
2577 AstNode *res = ast_create_node(pc, NodeTypeReturnExpr, try_token);
2578 res->data.return_expr.kind = ReturnKindError;
2579 return res;
2580 }
2581
2582 TokenIndex await = eat_token_if(pc, TokenIdKeywordAwait);
2583 if (await != 0) {
2584 AstNode *res = ast_create_node(pc, NodeTypeAwaitExpr, await);
2585 return res;
2586 }
2587
2588 return nullptr;
2589}
2590
2591// PrefixTypeOp
2592// <- QUESTIONMARK
2593// / KEYWORD_anyframe MINUSRARROW
2594// / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile)*
2595// / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile)*
2596static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
2597 TokenIndex questionmark = eat_token_if(pc, TokenIdQuestion);
2598 if (questionmark != 0) {
2599 AstNode *res = ast_create_node(pc, NodeTypePrefixOpExpr, questionmark);
2600 res->data.prefix_op_expr.prefix_op = PrefixOpOptional;
2601 return res;
2602 }
2603
2604 TokenIndex anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame);
2605 if (anyframe != 0) {
2606 if (eat_token_if(pc, TokenIdArrow) != 0) {
2607 AstNode *res = ast_create_node(pc, NodeTypeAnyFrameType, anyframe);
2608 return res;
2609 }
2610
2611 put_back_token(pc);
2612 }
2613
2614 TokenIndex arr_init_lbracket = eat_token_if(pc, TokenIdLBracket);
2615 if (arr_init_lbracket != 0) {
2616 TokenIndex underscore = eat_token_if(pc, TokenIdIdentifier);
2617 if (underscore == 0) {
2618 put_back_token(pc);
2619 } else if (!buf_eql_str(token_buf(pc, underscore), "_")) {
2620 put_back_token(pc);
2621 put_back_token(pc);
2622 } else {
2623 AstNode *sentinel = nullptr;
2624 TokenIndex colon = eat_token_if(pc, TokenIdColon);
2625 if (colon != 0) {
2626 sentinel = ast_expect(pc, ast_parse_expr);
2627 }
2628 expect_token(pc, TokenIdRBracket);
2629 AstNode *node = ast_create_node(pc, NodeTypeInferredArrayType, arr_init_lbracket);
2630 node->data.inferred_array_type.sentinel = sentinel;
2631 return node;
2632 }
2633 }
2634
2635
2636 AstNode *ptr = ast_parse_ptr_type_start(pc);
2637 if (ptr != nullptr) {
2638 assert(ptr->type == NodeTypePointerType);
2639 // We might get two pointers from *_ptr_type_start
2640 AstNode *child = ptr->data.pointer_type.op_expr;
2641 if (child == nullptr)
2642 child = ptr;
2643 while (true) {
2644 TokenIndex allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero);
2645 if (allowzero_token != 0) {
2646 child->data.pointer_type.allow_zero_token = allowzero_token;
2647 continue;
2648 }
2649
2650 if (eat_token_if(pc, TokenIdKeywordAlign) != 0) {
2651 expect_token(pc, TokenIdLParen);
2652 AstNode *align_expr = ast_expect(pc, ast_parse_expr);
2653 child->data.pointer_type.align_expr = align_expr;
2654 if (eat_token_if(pc, TokenIdColon) != 0) {
2655 TokenIndex bit_offset_start = expect_token(pc, TokenIdIntLiteral);
2656 expect_token(pc, TokenIdColon);
2657 TokenIndex host_int_bytes = expect_token(pc, TokenIdIntLiteral);
2658 child->data.pointer_type.bit_offset_start = bit_offset_start;
2659 child->data.pointer_type.host_int_bytes = host_int_bytes;
2660 }
2661 expect_token(pc, TokenIdRParen);
2662 continue;
2663 }
2664
2665 if (eat_token_if(pc, TokenIdKeywordConst) != 0) {
2666 child->data.pointer_type.is_const = true;
2667 continue;
2668 }
2669
2670 if (eat_token_if(pc, TokenIdKeywordVolatile) != 0) {
2671 child->data.pointer_type.is_volatile = true;
2672 continue;
2673 }
2674
2675 break;
2676 }
2677
2678 return ptr;
2679 }
2680
2681 AstNode *array = ast_parse_array_type_start(pc);
2682 if (array != nullptr) {
2683 assert(array->type == NodeTypeArrayType);
2684 while (true) {
2685 TokenIndex allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero);
2686 if (allowzero_token != 0) {
2687 array->data.array_type.allow_zero_token = allowzero_token;
2688 continue;
2689 }
2690
2691 AstNode *align_expr = ast_parse_byte_align(pc);
2692 if (align_expr != nullptr) {
2693 array->data.array_type.align_expr = align_expr;
2694 continue;
2695 }
2696
2697 if (eat_token_if(pc, TokenIdKeywordConst) != 0) {
2698 array->data.array_type.is_const = true;
2699 continue;
2700 }
2701
2702 if (eat_token_if(pc, TokenIdKeywordVolatile) != 0) {
2703 array->data.array_type.is_volatile = true;
2704 continue;
2705 }
2706 break;
2707 }
2708
2709 return array;
2710 }
2711
2712
2713 return nullptr;
2714}
2715
2716// SuffixOp
2717// <- LBRACKET Expr (DOT2 (Expr (COLON Expr)?)?)? RBRACKET
2718// / DOT IDENTIFIER
2719// / DOTASTERISK
2720// / DOTQUESTIONMARK
2721static AstNode *ast_parse_suffix_op(ParseContext *pc) {
2722 TokenIndex lbracket = eat_token_if(pc, TokenIdLBracket);
2723 if (lbracket != 0) {
2724 AstNode *start = ast_expect(pc, ast_parse_expr);
2725 AstNode *end = nullptr;
2726 if (eat_token_if(pc, TokenIdEllipsis2) != 0) {
2727 AstNode *sentinel = nullptr;
2728 end = ast_parse_expr(pc);
2729 if (eat_token_if(pc, TokenIdColon) != 0) {
2730 sentinel = ast_parse_expr(pc);
2731 }
2732 expect_token(pc, TokenIdRBracket);
2733
2734 AstNode *res = ast_create_node(pc, NodeTypeSliceExpr, lbracket);
2735 res->data.slice_expr.start = start;
2736 res->data.slice_expr.end = end;
2737 res->data.slice_expr.sentinel = sentinel;
2738 return res;
2739 }
2740
2741 expect_token(pc, TokenIdRBracket);
2742
2743 AstNode *res = ast_create_node(pc, NodeTypeArrayAccessExpr, lbracket);
2744 res->data.array_access_expr.subscript = start;
2745 return res;
2746 }
2747
2748 TokenIndex dot_asterisk = eat_token_if(pc, TokenIdDotStar);
2749 if (dot_asterisk != 0)
2750 return ast_create_node(pc, NodeTypePtrDeref, dot_asterisk);
2751
2752 TokenIndex dot = eat_token_if(pc, TokenIdDot);
2753 if (dot != 0) {
2754 if (eat_token_if(pc, TokenIdQuestion) != 0)
2755 return ast_create_node(pc, NodeTypeUnwrapOptional, dot);
2756
2757 TokenIndex ident = expect_token(pc, TokenIdIdentifier);
2758 AstNode *res = ast_create_node(pc, NodeTypeFieldAccessExpr, dot);
2759 res->data.field_access_expr.field_name = token_buf(pc, ident);
2760 return res;
2761 }
2762
2763 return nullptr;
2764}
2765
2766// FnCallArguments <- LPAREN ExprList RPAREN
2767static AstNode *ast_parse_fn_call_arguments(ParseContext *pc) {
2768 TokenIndex paren = eat_token_if(pc, TokenIdLParen);
2769 if (paren == 0)
2770 return nullptr;
2771
2772 ZigList<AstNode *> params = ast_parse_list(pc, TokenIdComma, ast_parse_expr);
2773 expect_token(pc, TokenIdRParen);
2774
2775 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, paren);
2776 res->data.fn_call_expr.params = params;
2777 res->data.fn_call_expr.seen = false;
2778 return res;
2779}
2780
2781// ArrayTypeStart <- LBRACKET Expr? RBRACKET
2782static AstNode *ast_parse_array_type_start(ParseContext *pc) {
2783 TokenIndex lbracket = eat_token_if(pc, TokenIdLBracket);
2784 if (lbracket == 0)
2785 return nullptr;
2786
2787 AstNode *size = ast_parse_expr(pc);
2788 AstNode *sentinel = nullptr;
2789 TokenIndex colon = eat_token_if(pc, TokenIdColon);
2790 if (colon != 0) {
2791 sentinel = ast_expect(pc, ast_parse_expr);
2792 }
2793 expect_token(pc, TokenIdRBracket);
2794 AstNode *res = ast_create_node(pc, NodeTypeArrayType, lbracket);
2795 res->data.array_type.size = size;
2796 res->data.array_type.sentinel = sentinel;
2797 return res;
2798}
2799
2800// PtrTypeStart
2801// <- ASTERISK
2802// / ASTERISK2
2803// / PTRUNKNOWN
2804// / PTRC
2805static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
2806 AstNode *sentinel = nullptr;
2807
2808 TokenIndex asterisk = eat_token_if(pc, TokenIdStar);
2809 if (asterisk != 0) {
2810 TokenIndex colon = eat_token_if(pc, TokenIdColon);
2811 if (colon != 0) {
2812 sentinel = ast_expect(pc, ast_parse_expr);
2813 }
2814 AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk);
2815 res->data.pointer_type.star_token = asterisk;
2816 res->data.pointer_type.sentinel = sentinel;
2817 return res;
2818 }
2819
2820 TokenIndex asterisk2 = eat_token_if(pc, TokenIdStarStar);
2821 if (asterisk2 != 0) {
2822 TokenIndex colon = eat_token_if(pc, TokenIdColon);
2823 if (colon != 0) {
2824 sentinel = ast_expect(pc, ast_parse_expr);
2825 }
2826 AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk2);
2827 AstNode *res2 = ast_create_node(pc, NodeTypePointerType, asterisk2);
2828 res->data.pointer_type.star_token = asterisk2;
2829 res2->data.pointer_type.star_token = asterisk2;
2830 res2->data.pointer_type.sentinel = sentinel;
2831 res->data.pointer_type.op_expr = res2;
2832 return res;
2833 }
2834
2835 TokenIndex lbracket = eat_token_if(pc, TokenIdLBracket);
2836 if (lbracket != 0) {
2837 TokenIndex star = eat_token_if(pc, TokenIdStar);
2838 if (star == 0) {
2839 put_back_token(pc);
2840 } else {
2841 TokenIndex c_tok = eat_token_if(pc, TokenIdIdentifier);
2842 if (c_tok != 0) {
2843 if (!buf_eql_str(token_buf(pc, c_tok), "c")) {
2844 put_back_token(pc); // c symbol
2845 } else {
2846 expect_token(pc, TokenIdRBracket);
2847 AstNode *res = ast_create_node(pc, NodeTypePointerType, lbracket);
2848 res->data.pointer_type.star_token = c_tok;
2849 return res;
2850 }
2851 }
2852
2853 TokenIndex colon = eat_token_if(pc, TokenIdColon);
2854 if (colon != 0) {
2855 sentinel = ast_expect(pc, ast_parse_expr);
2856 }
2857 expect_token(pc, TokenIdRBracket);
2858 AstNode *res = ast_create_node(pc, NodeTypePointerType, lbracket);
2859 res->data.pointer_type.star_token = lbracket;
2860 res->data.pointer_type.sentinel = sentinel;
2861 return res;
2862 }
2863 }
2864
2865 return nullptr;
2866}
2867
2868// ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE
2869static AstNode *ast_parse_container_decl_auto(ParseContext *pc) {
2870 AstNode *res = ast_parse_container_decl_type(pc);
2871 if (res == nullptr)
2872 return nullptr;
2873
2874 expect_token(pc, TokenIdLBrace);
2875 AstNodeContainerDecl members = ast_parse_container_members(pc);
2876 expect_token(pc, TokenIdRBrace);
2877
2878 res->data.container_decl.fields = members.fields;
2879 res->data.container_decl.decls = members.decls;
2880 res->data.container_decl.doc_comments = members.doc_comments;
2881 return res;
2882}
2883
2884// ContainerDeclType
2885// <- KEYWORD_struct (LPAREN Expr RPAREN)?
2886// / KEYWORD_enum (LPAREN Expr RPAREN)?
2887// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
2888// / KEYWORD_opaque
2889static AstNode *ast_parse_container_decl_type(ParseContext *pc) {
2890 TokenIndex first = eat_token_if(pc, TokenIdKeywordStruct);
2891 if (first != 0) {
2892 bool explicit_backing_int = false;
2893 if (eat_token_if(pc, TokenIdLParen) != 0) {
2894 explicit_backing_int = true;
2895 ast_expect(pc, ast_parse_expr);
2896 expect_token(pc, TokenIdRParen);
2897 }
2898 AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);
2899 res->data.container_decl.init_arg_expr = nullptr;
2900 res->data.container_decl.kind = ContainerKindStruct;
2901 // We want this to be an error in semantic analysis not parsing to make sharing
2902 // the test suite between stage1 and self hosted easier.
2903 res->data.container_decl.unsupported_explicit_backing_int = explicit_backing_int;
2904 return res;
2905 }
2906
2907 first = eat_token_if(pc, TokenIdKeywordOpaque);
2908 if (first != 0) {
2909 AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);
2910 res->data.container_decl.init_arg_expr = nullptr;
2911 res->data.container_decl.kind = ContainerKindOpaque;
2912 return res;
2913 }
2914
2915 first = eat_token_if(pc, TokenIdKeywordEnum);
2916 if (first != 0) {
2917 AstNode *init_arg_expr = nullptr;
2918 if (eat_token_if(pc, TokenIdLParen) != 0) {
2919 init_arg_expr = ast_expect(pc, ast_parse_expr);
2920 expect_token(pc, TokenIdRParen);
2921 }
2922 AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);
2923 res->data.container_decl.init_arg_expr = init_arg_expr;
2924 res->data.container_decl.kind = ContainerKindEnum;
2925 return res;
2926 }
2927
2928 first = eat_token_if(pc, TokenIdKeywordUnion);
2929 if (first != 0) {
2930 AstNode *init_arg_expr = nullptr;
2931 bool auto_enum = false;
2932 if (eat_token_if(pc, TokenIdLParen) != 0) {
2933 if (eat_token_if(pc, TokenIdKeywordEnum) != 0) {
2934 auto_enum = true;
2935 if (eat_token_if(pc, TokenIdLParen) != 0) {
2936 init_arg_expr = ast_expect(pc, ast_parse_expr);
2937 expect_token(pc, TokenIdRParen);
2938 }
2939 } else {
2940 init_arg_expr = ast_expect(pc, ast_parse_expr);
2941 }
2942
2943 expect_token(pc, TokenIdRParen);
2944 }
2945
2946 AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);
2947 res->data.container_decl.init_arg_expr = init_arg_expr;
2948 res->data.container_decl.auto_enum = auto_enum;
2949 res->data.container_decl.kind = ContainerKindUnion;
2950 return res;
2951 }
2952
2953 return nullptr;
2954}
2955
2956// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN
2957static AstNode *ast_parse_byte_align(ParseContext *pc) {
2958 if (eat_token_if(pc, TokenIdKeywordAlign) == 0)
2959 return nullptr;
2960
2961 expect_token(pc, TokenIdLParen);
2962 AstNode *res = ast_expect(pc, ast_parse_expr);
2963 expect_token(pc, TokenIdRParen);
2964 return res;
2965}
2966
2967static void visit_field(AstNode **node, void (*visit)(AstNode **, void *context), void *context) {
2968 if (*node) {
2969 visit(node, context);
2970 }
2971}
2972
2973static void visit_node_list(ZigList<AstNode *> *list, void (*visit)(AstNode **, void *context), void *context) {
2974 if (list) {
2975 for (size_t i = 0; i < list->length; i += 1) {
2976 visit(&list->at(i), context);
2977 }
2978 }
2979}
2980
2981void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context) {
2982 switch (node->type) {
2983 case NodeTypeFnProto:
2984 visit_field(&node->data.fn_proto.return_type, visit, context);
2985 visit_node_list(&node->data.fn_proto.params, visit, context);
2986 visit_field(&node->data.fn_proto.align_expr, visit, context);
2987 visit_field(&node->data.fn_proto.section_expr, visit, context);
2988 break;
2989 case NodeTypeFnDef:
2990 visit_field(&node->data.fn_def.fn_proto, visit, context);
2991 visit_field(&node->data.fn_def.body, visit, context);
2992 break;
2993 case NodeTypeParamDecl:
2994 visit_field(&node->data.param_decl.type, visit, context);
2995 break;
2996 case NodeTypeBlock:
2997 visit_node_list(&node->data.block.statements, visit, context);
2998 break;
2999 case NodeTypeGroupedExpr:
3000 visit_field(&node->data.grouped_expr, visit, context);
3001 break;
3002 case NodeTypeReturnExpr:
3003 visit_field(&node->data.return_expr.expr, visit, context);
3004 break;
3005 case NodeTypeDefer:
3006 visit_field(&node->data.defer.expr, visit, context);
3007 visit_field(&node->data.defer.err_payload, visit, context);
3008 break;
3009 case NodeTypeVariableDeclaration:
3010 visit_field(&node->data.variable_declaration.type, visit, context);
3011 visit_field(&node->data.variable_declaration.expr, visit, context);
3012 visit_field(&node->data.variable_declaration.align_expr, visit, context);
3013 visit_field(&node->data.variable_declaration.section_expr, visit, context);
3014 break;
3015 case NodeTypeTestDecl:
3016 visit_field(&node->data.test_decl.body, visit, context);
3017 break;
3018 case NodeTypeBinOpExpr:
3019 visit_field(&node->data.bin_op_expr.op1, visit, context);
3020 visit_field(&node->data.bin_op_expr.op2, visit, context);
3021 break;
3022 case NodeTypeCatchExpr:
3023 visit_field(&node->data.unwrap_err_expr.op1, visit, context);
3024 visit_field(&node->data.unwrap_err_expr.symbol, visit, context);
3025 visit_field(&node->data.unwrap_err_expr.op2, visit, context);
3026 break;
3027 case NodeTypeIntLiteral:
3028 // none
3029 break;
3030 case NodeTypeFloatLiteral:
3031 // none
3032 break;
3033 case NodeTypeStringLiteral:
3034 // none
3035 break;
3036 case NodeTypeCharLiteral:
3037 // none
3038 break;
3039 case NodeTypeIdentifier:
3040 // none
3041 break;
3042 case NodeTypePrefixOpExpr:
3043 visit_field(&node->data.prefix_op_expr.primary_expr, visit, context);
3044 break;
3045 case NodeTypeFnCallExpr:
3046 visit_field(&node->data.fn_call_expr.fn_ref_expr, visit, context);
3047 visit_node_list(&node->data.fn_call_expr.params, visit, context);
3048 break;
3049 case NodeTypeArrayAccessExpr:
3050 visit_field(&node->data.array_access_expr.array_ref_expr, visit, context);
3051 visit_field(&node->data.array_access_expr.subscript, visit, context);
3052 break;
3053 case NodeTypeSliceExpr:
3054 visit_field(&node->data.slice_expr.array_ref_expr, visit, context);
3055 visit_field(&node->data.slice_expr.start, visit, context);
3056 visit_field(&node->data.slice_expr.end, visit, context);
3057 visit_field(&node->data.slice_expr.sentinel, visit, context);
3058 break;
3059 case NodeTypeFieldAccessExpr:
3060 visit_field(&node->data.field_access_expr.struct_expr, visit, context);
3061 break;
3062 case NodeTypePtrDeref:
3063 visit_field(&node->data.ptr_deref_expr.target, visit, context);
3064 break;
3065 case NodeTypeUnwrapOptional:
3066 visit_field(&node->data.unwrap_optional.expr, visit, context);
3067 break;
3068 case NodeTypeUsingNamespace:
3069 visit_field(&node->data.using_namespace.expr, visit, context);
3070 break;
3071 case NodeTypeIfBoolExpr:
3072 visit_field(&node->data.if_bool_expr.condition, visit, context);
3073 visit_field(&node->data.if_bool_expr.then_block, visit, context);
3074 visit_field(&node->data.if_bool_expr.else_node, visit, context);
3075 break;
3076 case NodeTypeIfErrorExpr:
3077 visit_field(&node->data.if_err_expr.target_node, visit, context);
3078 visit_field(&node->data.if_err_expr.then_node, visit, context);
3079 visit_field(&node->data.if_err_expr.else_node, visit, context);
3080 break;
3081 case NodeTypeIfOptional:
3082 visit_field(&node->data.test_expr.target_node, visit, context);
3083 visit_field(&node->data.test_expr.then_node, visit, context);
3084 visit_field(&node->data.test_expr.else_node, visit, context);
3085 break;
3086 case NodeTypeWhileExpr:
3087 visit_field(&node->data.while_expr.condition, visit, context);
3088 visit_field(&node->data.while_expr.body, visit, context);
3089 break;
3090 case NodeTypeForExpr:
3091 visit_field(&node->data.for_expr.elem_node, visit, context);
3092 visit_field(&node->data.for_expr.array_expr, visit, context);
3093 visit_field(&node->data.for_expr.index_node, visit, context);
3094 visit_field(&node->data.for_expr.body, visit, context);
3095 break;
3096 case NodeTypeSwitchExpr:
3097 visit_field(&node->data.switch_expr.expr, visit, context);
3098 visit_node_list(&node->data.switch_expr.prongs, visit, context);
3099 break;
3100 case NodeTypeSwitchProng:
3101 visit_node_list(&node->data.switch_prong.items, visit, context);
3102 visit_field(&node->data.switch_prong.var_symbol, visit, context);
3103 visit_field(&node->data.switch_prong.expr, visit, context);
3104 break;
3105 case NodeTypeSwitchRange:
3106 visit_field(&node->data.switch_range.start, visit, context);
3107 visit_field(&node->data.switch_range.end, visit, context);
3108 break;
3109 case NodeTypeCompTime:
3110 visit_field(&node->data.comptime_expr.expr, visit, context);
3111 break;
3112 case NodeTypeNoSuspend:
3113 visit_field(&node->data.comptime_expr.expr, visit, context);
3114 break;
3115 case NodeTypeBreak:
3116 // none
3117 break;
3118 case NodeTypeContinue:
3119 // none
3120 break;
3121 case NodeTypeUnreachable:
3122 // none
3123 break;
3124 case NodeTypeAsmExpr:
3125 for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1) {
3126 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
3127 visit_field(&asm_input->expr, visit, context);
3128 }
3129 for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1) {
3130 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
3131 visit_field(&asm_output->return_type, visit, context);
3132 }
3133 break;
3134 case NodeTypeContainerDecl:
3135 visit_node_list(&node->data.container_decl.fields, visit, context);
3136 visit_node_list(&node->data.container_decl.decls, visit, context);
3137 visit_field(&node->data.container_decl.init_arg_expr, visit, context);
3138 break;
3139 case NodeTypeStructField:
3140 visit_field(&node->data.struct_field.type, visit, context);
3141 visit_field(&node->data.struct_field.value, visit, context);
3142 break;
3143 case NodeTypeContainerInitExpr:
3144 visit_field(&node->data.container_init_expr.type, visit, context);
3145 visit_node_list(&node->data.container_init_expr.entries, visit, context);
3146 break;
3147 case NodeTypeStructValueField:
3148 visit_field(&node->data.struct_val_field.expr, visit, context);
3149 break;
3150 case NodeTypeArrayType:
3151 visit_field(&node->data.array_type.size, visit, context);
3152 visit_field(&node->data.array_type.sentinel, visit, context);
3153 visit_field(&node->data.array_type.child_type, visit, context);
3154 visit_field(&node->data.array_type.align_expr, visit, context);
3155 break;
3156 case NodeTypeInferredArrayType:
3157 visit_field(&node->data.array_type.sentinel, visit, context);
3158 visit_field(&node->data.array_type.child_type, visit, context);
3159 break;
3160 case NodeTypeAnyFrameType:
3161 visit_field(&node->data.anyframe_type.payload_type, visit, context);
3162 break;
3163 case NodeTypeErrorType:
3164 // none
3165 break;
3166 case NodeTypePointerType:
3167 visit_field(&node->data.pointer_type.sentinel, visit, context);
3168 visit_field(&node->data.pointer_type.align_expr, visit, context);
3169 visit_field(&node->data.pointer_type.op_expr, visit, context);
3170 break;
3171 case NodeTypeErrorSetDecl:
3172 visit_node_list(&node->data.err_set_decl.decls, visit, context);
3173 break;
3174 case NodeTypeErrorSetField:
3175 visit_field(&node->data.err_set_field.field_name, visit, context);
3176 break;
3177 case NodeTypeResume:
3178 visit_field(&node->data.resume_expr.expr, visit, context);
3179 break;
3180 case NodeTypeAwaitExpr:
3181 visit_field(&node->data.await_expr.expr, visit, context);
3182 break;
3183 case NodeTypeSuspend:
3184 visit_field(&node->data.suspend.block, visit, context);
3185 break;
3186 case NodeTypeEnumLiteral:
3187 case NodeTypeAnyTypeField:
3188 break;
3189 }
3190}
3191
3192Error source_string_literal_buf(const char *source, Buf *out, size_t *bad_index) {
3193 size_t byte_offset = 0;
3194
3195 assert(source[byte_offset] == '"');
3196 byte_offset += 1;
3197
3198 buf_resize(out, 0);
3199
3200 uint32_t codepoint;
3201
3202 enum {
3203 StateStart,
3204 StateBackslash,
3205 StateUnicodeLBrace,
3206 StateUnicodeDigit,
3207 } state = StateStart;
3208 for (;;byte_offset += 1) {
3209 switch (state) {
3210 case StateStart: switch (source[byte_offset]) {
3211 case '\\':
3212 state = StateBackslash;
3213 continue;
3214 case '\n':
3215 *bad_index = byte_offset;
3216 return ErrorInvalidCharacter;
3217 case '"':
3218 return ErrorNone;
3219 default:
3220 buf_append_char(out, source[byte_offset]);
3221 continue;
3222 }
3223 case StateBackslash: switch (source[byte_offset]) {
3224 case 'n':
3225 buf_append_char(out, '\n');
3226 state = StateStart;
3227 continue;
3228 case 'r':
3229 buf_append_char(out, '\r');
3230 state = StateStart;
3231 continue;
3232 case '\\':
3233 buf_append_char(out, '\\');
3234 state = StateStart;
3235 continue;
3236 case 't':
3237 buf_append_char(out, '\t');
3238 state = StateStart;
3239 continue;
3240 case '\'':
3241 buf_append_char(out, '\'');
3242 state = StateStart;
3243 continue;
3244 case '"':
3245 buf_append_char(out, '"');
3246 state = StateStart;
3247 continue;
3248 case 'x': {
3249 byte_offset += 1;
3250 uint8_t digit1;
3251 if (source[byte_offset] >= '0' && source[byte_offset] <= '9') {
3252 digit1 = source[byte_offset] - '0';
3253 } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') {
3254 digit1 = source[byte_offset] - 'a' + 10;
3255 } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') {
3256 digit1 = source[byte_offset] - 'A' + 10;
3257 } else {
3258 *bad_index = byte_offset;
3259 return ErrorInvalidCharacter;
3260 }
3261
3262 byte_offset += 1;
3263 uint8_t digit0;
3264 if (source[byte_offset] >= '0' && source[byte_offset] <= '9') {
3265 digit0 = source[byte_offset] - '0';
3266 } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') {
3267 digit0 = source[byte_offset] - 'a' + 10;
3268 } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') {
3269 digit0 = source[byte_offset] - 'A' + 10;
3270 } else {
3271 *bad_index = byte_offset;
3272 return ErrorInvalidCharacter;
3273 }
3274
3275 buf_append_char(out, digit1 * 16 + digit0);
3276 state = StateStart;
3277 continue;
3278 }
3279 case 'u':
3280 state = StateUnicodeLBrace;
3281 continue;
3282 default:
3283 *bad_index = byte_offset;
3284 return ErrorInvalidCharacter;
3285 }
3286 case StateUnicodeLBrace: switch (source[byte_offset]) {
3287 case '{':
3288 state = StateUnicodeDigit;
3289 codepoint = 0;
3290 continue;
3291 default:
3292 *bad_index = byte_offset;
3293 return ErrorInvalidCharacter;
3294 }
3295 case StateUnicodeDigit: {
3296 uint8_t digit;
3297 if (source[byte_offset] >= '0' && source[byte_offset] <= '9') {
3298 digit = source[byte_offset] - '0';
3299 } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') {
3300 digit = source[byte_offset] - 'a' + 10;
3301 } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') {
3302 digit = source[byte_offset] - 'A' + 10;
3303 } else if (source[byte_offset] == '}') {
3304 if (codepoint < 0x80) {
3305 buf_append_char(out, codepoint);
3306 } else if (codepoint < 0x800) {
3307 buf_append_char(out, 0xc0 | (codepoint >> 6));
3308 buf_append_char(out, 0x80 | (codepoint & 0x3f));
3309 } else if (codepoint < 0x10000) {
3310 buf_append_char(out, 0xe0 | (codepoint >> 12));
3311 buf_append_char(out, 0x80 | ((codepoint >> 6) & 0x3f));
3312 buf_append_char(out, 0x80 | (codepoint & 0x3f));
3313 } else if (codepoint < 0x110000) {
3314 buf_append_char(out, 0xf0 | (codepoint >> 18));
3315 buf_append_char(out, 0x80 | ((codepoint >> 12) & 0x3f));
3316 buf_append_char(out, 0x80 | ((codepoint >> 6) & 0x3f));
3317 buf_append_char(out, 0x80 | (codepoint & 0x3f));
3318 } else {
3319 *bad_index = byte_offset;
3320 return ErrorUnicodePointTooLarge;
3321 }
3322 state = StateStart;
3323 continue;
3324 } else {
3325 *bad_index = byte_offset;
3326 return ErrorInvalidCharacter;
3327 }
3328 codepoint = codepoint * 16 + digit;
3329 continue;
3330 }
3331 }
3332 }
3333 zig_unreachable();
3334}
3335
3336static uint32_t utf8_code_point(const uint8_t *bytes) {
3337 if (bytes[0] <= 0x7f) {
3338 return bytes[0];
3339 } else if (bytes[0] >= 0xc0 && bytes[0] <= 0xdf) {
3340 uint32_t result = bytes[0] & 0x1f;
3341 result <<= 6;
3342 result |= bytes[1] & 0x3f;
3343 return result;
3344 } else if (bytes[0] >= 0xe0 && bytes[0] <= 0xef) {
3345 uint32_t result = bytes[0] & 0xf;
3346
3347 result <<= 6;
3348 result |= bytes[1] & 0x3f;
3349
3350 result <<= 6;
3351 result |= bytes[2] & 0x3f;
3352
3353 return result;
3354 } else if (bytes[0] >= 0xf0 && bytes[0] <= 0xf7) {
3355 uint32_t result = bytes[0] & 0x7;
3356
3357 result <<= 6;
3358 result |= bytes[1] & 0x3f;
3359
3360 result <<= 6;
3361 result |= bytes[2] & 0x3f;
3362
3363 result <<= 6;
3364 result |= bytes[3] & 0x3f;
3365
3366 return result;
3367 } else {
3368 zig_unreachable();
3369 }
3370}
3371
3372Error source_char_literal(const char *source, uint32_t *result, size_t *bad_index) {
3373 if (source[0] != '\\') {
3374 *result = utf8_code_point((const uint8_t *)source);
3375 return ErrorNone;
3376 }
3377
3378 uint32_t byte_offset = 1;
3379 uint32_t codepoint;
3380
3381 enum State {
3382 StateBackslash,
3383 StateUnicodeLBrace,
3384 StateUnicodeDigit,
3385 } state = StateBackslash;
3386
3387 for (;;byte_offset += 1) {
3388 switch (state) {
3389 case StateBackslash: switch (source[byte_offset]) {
3390 case 'n':
3391 *result = '\n';
3392 return ErrorNone;
3393 case 'r':
3394 *result = '\r';
3395 return ErrorNone;
3396 case '\\':
3397 *result = '\\';
3398 return ErrorNone;
3399 case 't':
3400 *result = '\t';
3401 return ErrorNone;
3402 case '\'':
3403 *result = '\'';
3404 return ErrorNone;
3405 case '"':
3406 *result = '"';
3407 return ErrorNone;
3408 case 'x': {
3409 byte_offset += 1;
3410 uint8_t digit1;
3411 if (source[byte_offset] >= '0' && source[byte_offset] <= '9') {
3412 digit1 = source[byte_offset] - '0';
3413 } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') {
3414 digit1 = source[byte_offset] - 'a' + 10;
3415 } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') {
3416 digit1 = source[byte_offset] - 'A' + 10;
3417 } else {
3418 *bad_index = byte_offset;
3419 return ErrorInvalidCharacter;
3420 }
3421
3422 byte_offset += 1;
3423 uint8_t digit0;
3424 if (source[byte_offset] >= '0' && source[byte_offset] <= '9') {
3425 digit0 = source[byte_offset] - '0';
3426 } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') {
3427 digit0 = source[byte_offset] - 'a' + 10;
3428 } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') {
3429 digit0 = source[byte_offset] - 'A' + 10;
3430 } else {
3431 *bad_index = byte_offset;
3432 return ErrorInvalidCharacter;
3433 }
3434
3435 *result = digit1 * 16 + digit0;
3436 return ErrorNone;
3437 }
3438 case 'u':
3439 state = StateUnicodeLBrace;
3440 continue;
3441 default:
3442 *bad_index = byte_offset;
3443 return ErrorInvalidCharacter;
3444 }
3445 case StateUnicodeLBrace: switch (source[byte_offset]) {
3446 case '{':
3447 state = StateUnicodeDigit;
3448 codepoint = 0;
3449 continue;
3450 default:
3451 *bad_index = byte_offset;
3452 return ErrorInvalidCharacter;
3453 }
3454 case StateUnicodeDigit: {
3455 uint8_t digit;
3456 if (source[byte_offset] >= '0' && source[byte_offset] <= '9') {
3457 digit = source[byte_offset] - '0';
3458 } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') {
3459 digit = source[byte_offset] - 'a' + 10;
3460 } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') {
3461 digit = source[byte_offset] - 'A' + 10;
3462 } else if (source[byte_offset] == '}') {
3463 if (codepoint < 0x110000) {
3464 *result = codepoint;
3465 return ErrorNone;
3466 } else {
3467 *bad_index = byte_offset;
3468 return ErrorUnicodePointTooLarge;
3469 }
3470 } else {
3471 *bad_index = byte_offset;
3472 return ErrorInvalidCharacter;
3473 }
3474 codepoint = codepoint * 16 + digit;
3475 continue;
3476 }
3477 }
3478 }
3479}
3480
3481static Buf *token_identifier_buf2(RootStruct *root_struct, TokenIndex token, bool *is_at_syntax) {
3482 Error err;
3483 const char *source = buf_ptr(root_struct->source_code);
3484 size_t byte_offset = root_struct->token_locs[token].offset;
3485 if (root_struct->token_ids[token] == TokenIdBuiltin) {
3486 byte_offset += 1;
3487 } else {
3488 assert(root_struct->token_ids[token] == TokenIdIdentifier);
3489 }
3490 assert(source[byte_offset] != '.'); // wrong token index
3491
3492 if (source[byte_offset] == '@') {
3493 *is_at_syntax = true;
3494 size_t bad_index;
3495 Buf *str = buf_alloc();
3496 if ((err = source_string_literal_buf(source + byte_offset + 1, str, &bad_index))) {
3497 ast_error_offset(root_struct, ErrColorAuto, token, bad_index + 1,
3498 buf_create_from_str("invalid string literal character"));
3499 }
3500 return str;
3501 } else {
3502 *is_at_syntax = false;
3503 size_t start = byte_offset;
3504 for (;; byte_offset += 1) {
3505 if (source[byte_offset] == 0) break;
3506 if ((source[byte_offset] >= 'a' && source[byte_offset] <= 'z') ||
3507 (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') ||
3508 (source[byte_offset] >= '0' && source[byte_offset] <= '9') ||
3509 source[byte_offset] == '_')
3510 {
3511 continue;
3512 }
3513 break;
3514 }
3515 return buf_create_from_mem(source + start, byte_offset - start);
3516 }
3517}
3518
3519Buf *token_identifier_buf(RootStruct *root_struct, TokenIndex token) {
3520 bool trash;
3521 return token_identifier_buf2(root_struct, token, &trash);
3522}
3523
3524Buf *node_identifier_buf(AstNode *node) {
3525 bool trash;
3526 return node_identifier_buf2(node, &trash);
3527}
3528
3529Buf *node_identifier_buf2(AstNode *node, bool *is_at_syntax) {
3530 assert(node->type == NodeTypeIdentifier);
3531 // Currently, stage1 runs astgen for every comptime function call,
3532 // resulting the allocation here wasting memory. As a workaround until
3533 // the code is adjusted to make astgen run only once per source node,
3534 // we memoize the result into the AST here.
3535 if (node->data.identifier.name == nullptr) {
3536 RootStruct *root_struct = node->owner->data.structure.root_struct;
3537 node->data.identifier.name = token_identifier_buf2(root_struct, node->main_token,
3538 &node->data.identifier.is_at_syntax);
3539 }
3540 *is_at_syntax = node->data.identifier.is_at_syntax;
3541 return node->data.identifier.name;
3542}
3543
3544void token_number_literal_bigint(RootStruct *root_struct, BigInt *result, TokenIndex token) {
3545 const char *source = buf_ptr(root_struct->source_code);
3546 uint32_t byte_offset = root_struct->token_locs[token].offset;
3547
3548 bigint_init_unsigned(result, 0);
3549 BigInt radix_bi;
3550
3551 if (source[byte_offset] == '0') {
3552 byte_offset += 1;
3553 switch (source[byte_offset]) {
3554 case 'b':
3555 byte_offset += 1;
3556 bigint_init_unsigned(&radix_bi, 2);
3557 break;
3558 case 'o':
3559 byte_offset += 1;
3560 bigint_init_unsigned(&radix_bi, 8);
3561 break;
3562 case 'x':
3563 byte_offset += 1;
3564 bigint_init_unsigned(&radix_bi, 16);
3565 break;
3566 default:
3567 bigint_init_unsigned(&radix_bi, 10);
3568 break;
3569 }
3570 } else {
3571 bigint_init_unsigned(&radix_bi, 10);
3572 }
3573
3574 BigInt digit_value_bi = {};
3575 BigInt multiplied = {};
3576
3577 for (;source[byte_offset] != 0; byte_offset += 1) {
3578 uint8_t digit;
3579 if (source[byte_offset] >= '0' && source[byte_offset] <= '9') {
3580 digit = source[byte_offset] - '0';
3581 } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') {
3582 digit = source[byte_offset] - 'a' + 10;
3583 } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') {
3584 digit = source[byte_offset] - 'A' + 10;
3585 } else if (source[byte_offset] == '_') {
3586 continue;
3587 } else {
3588 break;
3589 }
3590 bigint_deinit(&digit_value_bi);
3591 bigint_init_unsigned(&digit_value_bi, digit);
3592
3593 bigint_deinit(&multiplied);
3594 bigint_mul(&multiplied, result, &radix_bi);
3595
3596 bigint_add(result, &multiplied, &digit_value_bi);
3597 }
3598
3599 bigint_deinit(&digit_value_bi);
3600 bigint_deinit(&multiplied);
3601 bigint_deinit(&radix_bi);
3602}
3603
src/stage1/parser.hpp deleted-29
...@@ -1,29 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_PARSER_HPP
9#define ZIG_PARSER_HPP
10
11#include "all_types.hpp"
12#include "tokenizer.hpp"
13#include "errmsg.hpp"
14
15AstNode * ast_parse(Buf *buf, ZigType *owner, ErrColor err_color);
16
17void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context);
18
19Buf *node_identifier_buf(AstNode *node);
20Buf *node_identifier_buf2(AstNode *node, bool *is_at_syntax);
21
22Buf *token_identifier_buf(RootStruct *root_struct, TokenIndex token);
23
24void token_number_literal_bigint(RootStruct *root_struct, BigInt *result, TokenIndex token);
25
26Error source_string_literal_buf(const char *source, Buf *out, size_t *bad_index);
27Error source_char_literal(const char *source, uint32_t *out, size_t *bad_index);
28
29#endif
src/stage1/range_set.cpp deleted-74
...@@ -1,74 +0,0 @@
1#include "range_set.hpp"
2
3AstNode *rangeset_add_range(RangeSet *rs, BigInt *first, BigInt *last, AstNode *source_node) {
4 for (size_t i = 0; i < rs->src_range_list.length; i += 1) {
5 RangeWithSrc *range_with_src = &rs->src_range_list.at(i);
6 Range *range = &range_with_src->range;
7 if ((bigint_cmp(first, &range->first) == CmpLT && bigint_cmp(last, &range->first) == CmpLT) ||
8 (bigint_cmp(first, &range->last) == CmpGT && bigint_cmp(last, &range->last) == CmpGT))
9 {
10 // first...last is completely before/after `range`
11 }
12 else
13 {
14 return range_with_src->source_node;
15 }
16 }
17 rs->src_range_list.append({{*first, *last}, source_node});
18
19 return nullptr;
20
21}
22
23static int compare_rangeset(const void *a, const void *b) {
24 const Range *r1 = &static_cast<const RangeWithSrc*>(a)->range;
25 const Range *r2 = &static_cast<const RangeWithSrc*>(b)->range;
26 // Assume no two ranges overlap
27 switch (bigint_cmp(&r1->first, &r2->first)) {
28 case CmpLT: return -1;
29 case CmpGT: return 1;
30 case CmpEQ: return 0;
31 }
32 zig_unreachable();
33}
34
35void rangeset_sort(RangeSet *rs) {
36 if (rs->src_range_list.length > 1) {
37 qsort(rs->src_range_list.items, rs->src_range_list.length,
38 sizeof(RangeWithSrc), compare_rangeset);
39 }
40}
41
42bool rangeset_spans(RangeSet *rs, BigInt *first, BigInt *last) {
43 if (rs->src_range_list.length == 0)
44 return false;
45
46 rangeset_sort(rs);
47
48 const Range *first_range = &rs->src_range_list.at(0).range;
49 if (bigint_cmp(&first_range->first, first) != CmpEQ)
50 return false;
51
52 const Range *last_range = &rs->src_range_list.last().range;
53 if (bigint_cmp(&last_range->last, last) != CmpEQ)
54 return false;
55
56 BigInt one;
57 bigint_init_unsigned(&one, 1);
58
59 // Make sure there are no holes in the first...last range
60 for (size_t i = 1; i < rs->src_range_list.length; i++) {
61 const Range *range = &rs->src_range_list.at(i).range;
62 const Range *prev_range = &rs->src_range_list.at(i - 1).range;
63
64 assert(bigint_cmp(&prev_range->last, &range->first) == CmpLT);
65
66 BigInt last_plus_one;
67 bigint_add(&last_plus_one, &prev_range->last, &one);
68
69 if (bigint_cmp(&last_plus_one, &range->first) != CmpEQ)
70 return false;
71 }
72
73 return true;
74}
src/stage1/range_set.hpp deleted-30
...@@ -1,30 +0,0 @@
1/*
2 * Copyright (c) 2017 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_RANGE_SET_HPP
9#define ZIG_RANGE_SET_HPP
10
11#include "all_types.hpp"
12
13struct Range {
14 BigInt first;
15 BigInt last;
16};
17
18struct RangeWithSrc {
19 Range range;
20 AstNode *source_node;
21};
22
23struct RangeSet {
24 ZigList<RangeWithSrc> src_range_list;
25};
26
27AstNode *rangeset_add_range(RangeSet *rs, BigInt *first, BigInt *last, AstNode *source_node);
28bool rangeset_spans(RangeSet *rs, BigInt *first, BigInt *last);
29
30#endif
src/stage1/softfloat.hpp deleted-77
...@@ -1,77 +0,0 @@
1/*
2 * Copyright (c) 2017 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_SOFTFLOAT_HPP
9#define ZIG_SOFTFLOAT_HPP
10
11extern "C" {
12#include "softfloat.h"
13}
14
15#include "zigendian.h"
16
17static inline float16_t zig_double_to_f16(double x) {
18 float64_t y;
19 static_assert(sizeof(x) == sizeof(y), "");
20 memcpy(&y, &x, sizeof(x));
21 return f64_to_f16(y);
22}
23
24static inline void zig_double_to_extF80M(double x, extFloat80_t *result) {
25 float64_t y;
26 static_assert(sizeof(x) == sizeof(y), "");
27 memcpy(&y, &x, sizeof(x));
28 f64_to_extF80M(y, result);
29}
30
31static inline void zig_double_to_f128M(double x, float128_t *result) {
32 float64_t y;
33 static_assert(sizeof(x) == sizeof(y), "");
34 memcpy(&y, &x, sizeof(x));
35 f64_to_f128M(y, result);
36}
37
38
39// Return value is safe to coerce to float even when |x| is NaN or Infinity.
40static inline double zig_f16_to_double(float16_t x) {
41 float64_t y = f16_to_f64(x);
42 double z;
43 static_assert(sizeof(y) == sizeof(z), "");
44 memcpy(&z, &y, sizeof(y));
45 return z;
46}
47
48static inline bool zig_f16_isNaN(float16_t a) {
49 union { uint16_t ui; float16_t f; } uA;
50 uA.f = a;
51 return 0x7C00 < (uA.ui & 0x7FFF);
52}
53
54static inline bool zig_f128_isNaN(float128_t *aPtr) {
55 uint64_t hi, lo;
56
57 #if defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
58 hi = aPtr->v[1];
59 lo = aPtr->v[0];
60 #elif defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN
61 hi = aPtr->v[0];
62 lo = aPtr->v[1];
63 #else
64 #error Unsupported endian
65 #endif
66
67 uint64_t absA64 = hi & UINT64_C(0x7FFFFFFFFFFFFFFF);
68 return
69 (UINT64_C(0x7FFF000000000000) < absA64)
70 || ((absA64 == UINT64_C(0x7FFF000000000000)) && lo);
71}
72
73static inline bool zig_extF80_isNaN(extFloat80_t *aPtr) {
74 return (aPtr->signExp & 0x7FFF) == 0x7FFF && aPtr->signif & UINT64_C(0x7FFFFFFFFFFFFFFF);
75}
76
77#endif
src/stage1/softfloat_ext.cpp deleted-71
...@@ -1,71 +0,0 @@
1#include "softfloat_ext.hpp"
2#include "zigendian.h"
3
4extern "C" {
5 #include "softfloat.h"
6}
7
8void f128M_abs(const float128_t *aPtr, float128_t *zPtr) {
9 // Clear the sign bit.
10#if ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
11 zPtr->v[1] = aPtr->v[1] & ~(UINT64_C(1) << 63);
12 zPtr->v[0] = aPtr->v[0];
13#elif ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN
14 zPtr->v[0] = aPtr->v[0] & ~(UINT64_C(1) << 63);
15 zPtr->v[1] = aPtr->v[1];
16#else
17#error Unsupported endian
18#endif
19}
20
21void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) {
22 float128_t zero_float;
23 ui32_to_f128M(0, &zero_float);
24 if (f128M_lt(aPtr, &zero_float)) {
25 f128M_roundToInt(aPtr, softfloat_round_max, false, zPtr);
26 } else {
27 f128M_roundToInt(aPtr, softfloat_round_min, false, zPtr);
28 }
29}
30
31void f128M_neg(const float128_t *aPtr, float128_t *zPtr) {
32 // Toggle the sign bit.
33#if ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
34 zPtr->v[1] = aPtr->v[1] ^ (UINT64_C(1) << 63);
35 zPtr->v[0] = aPtr->v[0];
36#elif ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN
37 zPtr->v[0] = aPtr->v[0] ^ (UINT64_C(1) << 63);
38 zPtr->v[1] = aPtr->v[1];
39#else
40#error Unsupported endian
41#endif
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 deleted-16
...@@ -1,16 +0,0 @@
1#ifndef ZIG_SOFTFLOAT_EXT_HPP
2#define ZIG_SOFTFLOAT_EXT_HPP
3
4#include "softfloat_types.h"
5
6void f128M_abs(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);
9
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
14float16_t f16_neg(const float16_t a);
15
16#endif
\ No newline at end of file
src/stage1/stage1.cpp deleted-131
...@@ -1,131 +0,0 @@
1/*
2 * Copyright (c) 2020 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "stage1.h"
9#include "os.hpp"
10#include "all_types.hpp"
11#include "codegen.hpp"
12
13void zig_stage1_os_init(void) {
14 os_init();
15 mem::init();
16 init_all_targets();
17}
18
19struct ZigStage1 *zig_stage1_create(BuildMode optimize_mode,
20 const char *main_pkg_path_ptr, size_t main_pkg_path_len,
21 const char *root_src_path_ptr, size_t root_src_path_len,
22 const char *zig_lib_dir_ptr, size_t zig_lib_dir_len,
23 const ZigTarget *target, bool is_test_build)
24{
25 Buf *main_pkg_path = (main_pkg_path_len == 0) ?
26 nullptr : buf_create_from_mem(main_pkg_path_ptr, main_pkg_path_len);
27 Buf *root_src_path = buf_create_from_mem(root_src_path_ptr, root_src_path_len);
28 Buf *zig_lib_dir = buf_create_from_mem(zig_lib_dir_ptr, zig_lib_dir_len);
29 CodeGen *g = codegen_create(main_pkg_path, root_src_path, target, optimize_mode,
30 zig_lib_dir, is_test_build);
31 return &g->stage1;
32}
33
34void zig_stage1_destroy(struct ZigStage1 *stage1) {
35 CodeGen *codegen = reinterpret_cast<CodeGen *>(stage1);
36 codegen_destroy(codegen);
37}
38
39static void add_package(CodeGen *g, ZigStage1Pkg *stage1_pkg, ZigPackage *pkg) {
40 for (size_t i = 0; i < stage1_pkg->children_len; i += 1) {
41 ZigStage1Pkg *child_cli_pkg = stage1_pkg->children_ptr[i];
42
43 Buf *dirname = buf_alloc();
44 Buf *basename = buf_alloc();
45 os_path_split(buf_create_from_mem(child_cli_pkg->path_ptr, child_cli_pkg->path_len), dirname, basename);
46
47 ZigPackage *child_pkg = codegen_create_package(g, buf_ptr(dirname), buf_ptr(basename),
48 buf_ptr(buf_sprintf("%s.%.*s", buf_ptr(&pkg->pkg_path),
49 (int)child_cli_pkg->name_len, child_cli_pkg->name_ptr)));
50 auto entry = pkg->package_table.put_unique(
51 buf_create_from_mem(child_cli_pkg->name_ptr, child_cli_pkg->name_len),
52 child_pkg);
53 if (entry) {
54 ZigPackage *existing_pkg = entry->value;
55 Buf *full_path = buf_alloc();
56 os_path_join(&existing_pkg->root_src_dir, &existing_pkg->root_src_path, full_path);
57 fprintf(stderr, "Unable to add package '%.*s'->'%.*s': already exists as '%s'\n",
58 (int)child_cli_pkg->name_len, child_cli_pkg->name_ptr,
59 (int)child_cli_pkg->path_len, child_cli_pkg->path_ptr,
60 buf_ptr(full_path));
61 exit(EXIT_FAILURE);
62 }
63
64 add_package(g, child_cli_pkg, child_pkg);
65 }
66}
67
68void zig_stage1_build_object(struct ZigStage1 *stage1) {
69 CodeGen *g = reinterpret_cast<CodeGen *>(stage1);
70
71 g->root_out_name = buf_create_from_mem(stage1->root_name_ptr, stage1->root_name_len);
72 buf_init_from_mem(&g->o_file_output_path, stage1->emit_o_ptr, stage1->emit_o_len);
73 buf_init_from_mem(&g->h_file_output_path, stage1->emit_h_ptr, stage1->emit_h_len);
74 buf_init_from_mem(&g->asm_file_output_path, stage1->emit_asm_ptr, stage1->emit_asm_len);
75 buf_init_from_mem(&g->llvm_ir_file_output_path, stage1->emit_llvm_ir_ptr, stage1->emit_llvm_ir_len);
76 buf_init_from_mem(&g->bitcode_file_output_path, stage1->emit_bitcode_ptr, stage1->emit_bitcode_len);
77
78 if (stage1->builtin_zig_path_len != 0) {
79 g->builtin_zig_path = buf_create_from_mem(stage1->builtin_zig_path_ptr, stage1->builtin_zig_path_len);
80 }
81 if (stage1->test_filter_len != 0) {
82 g->test_filter = buf_create_from_mem(stage1->test_filter_ptr, stage1->test_filter_len);
83 }
84 if (stage1->test_name_prefix_len != 0) {
85 g->test_name_prefix = buf_create_from_mem(stage1->test_name_prefix_ptr, stage1->test_name_prefix_len);
86 }
87
88 g->link_mode_dynamic = stage1->link_mode_dynamic;
89 g->dll_export_fns = stage1->dll_export_fns;
90 g->have_pic = stage1->pic;
91 g->have_pie = stage1->pie;
92 g->have_lto = stage1->lto;
93 g->unwind_tables = stage1->unwind_tables;
94 g->have_stack_probing = stage1->enable_stack_probing;
95 g->red_zone = stage1->red_zone;
96 g->omit_frame_pointer = stage1->omit_frame_pointer;
97 g->is_single_threaded = stage1->is_single_threaded;
98 g->valgrind_enabled = stage1->valgrind_enabled;
99 g->tsan_enabled = stage1->tsan_enabled;
100 g->link_libc = stage1->link_libc;
101 g->link_libcpp = stage1->link_libcpp;
102 g->function_sections = stage1->function_sections;
103 g->include_compiler_rt = stage1->include_compiler_rt;
104
105 g->subsystem = stage1->subsystem;
106
107 g->enable_time_report = stage1->enable_time_report;
108 g->enable_stack_report = stage1->enable_stack_report;
109 g->test_is_evented = stage1->test_is_evented;
110
111 g->verbose_ir = stage1->verbose_ir;
112 g->verbose_llvm_ir = stage1->verbose_llvm_ir;
113 g->verbose_cimport = stage1->verbose_cimport;
114 g->verbose_llvm_cpu_features = stage1->verbose_llvm_cpu_features;
115
116 g->err_color = stage1->err_color;
117 g->code_model = stage1->code_model;
118
119 {
120 g->strip_debug_symbols = stage1->strip;
121 if (!target_has_debug_info(g->zig_target)) {
122 g->strip_debug_symbols = true;
123 }
124 }
125
126 g->main_progress_node = stage1->main_progress_node;
127
128 add_package(g, stage1->main_pkg, g->main_pkg);
129
130 codegen_build_object(g);
131}
src/stage1/stage1.h deleted-230
...@@ -1,230 +0,0 @@
1/*
2 * Copyright (c) 2020 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8// This file deals with exposing stage1 C++ code to stage2 Zig code.
9
10#ifndef ZIG_STAGE1_H
11#define ZIG_STAGE1_H
12
13#include "zig_llvm.h"
14
15#include <stddef.h>
16
17#ifdef __cplusplus
18#define ZIG_EXTERN_C extern "C"
19#else
20#define ZIG_EXTERN_C
21#endif
22
23// ABI warning
24enum ErrColor {
25 ErrColorAuto,
26 ErrColorOff,
27 ErrColorOn,
28};
29
30// ABI warning
31enum CodeModel {
32 CodeModelDefault,
33 CodeModelTiny,
34 CodeModelSmall,
35 CodeModelKernel,
36 CodeModelMedium,
37 CodeModelLarge,
38};
39
40// ABI warning
41enum TargetSubsystem {
42 TargetSubsystemConsole,
43 TargetSubsystemWindows,
44 TargetSubsystemPosix,
45 TargetSubsystemNative,
46 TargetSubsystemEfiApplication,
47 TargetSubsystemEfiBootServiceDriver,
48 TargetSubsystemEfiRom,
49 TargetSubsystemEfiRuntimeDriver,
50
51 // This means Zig should infer the subsystem.
52 // It's last so that the indexes of other items can line up
53 // with the enum in builtin.zig.
54 TargetSubsystemAuto
55};
56
57
58// ABI warning
59// Synchronize with std.Target.Os.Tag and target.cpp::os_list
60enum Os {
61 OsFreestanding,
62 OsAnanas,
63 OsCloudABI,
64 OsDragonFly,
65 OsFreeBSD,
66 OsFuchsia,
67 OsIOS,
68 OsKFreeBSD,
69 OsLinux,
70 OsLv2, // PS3
71 OsMacOSX,
72 OsNetBSD,
73 OsOpenBSD,
74 OsSolaris,
75 OsWindows,
76 OsZOS,
77 OsHaiku,
78 OsMinix,
79 OsRTEMS,
80 OsNaCl, // Native Client
81 OsAIX,
82 OsCUDA, // NVIDIA CUDA
83 OsNVCL, // NVIDIA OpenCL
84 OsAMDHSA, // AMD HSA Runtime
85 OsPS4,
86 OsPS5,
87 OsELFIAMCU,
88 OsTvOS, // Apple tvOS
89 OsWatchOS, // Apple watchOS
90 OsDriverKit, // Apple DriverKit
91 OsMesa3D,
92 OsContiki,
93 OsAMDPAL,
94 OsHermitCore,
95 OsHurd,
96 OsWASI,
97 OsEmscripten,
98 OsShaderModel, // DirectX ShaderModel
99 OsUefi,
100 OsOpenCL,
101 OsGLSL450,
102 OsVulkan,
103 OsPlan9,
104 OsOther,
105};
106
107// ABI warning
108struct ZigTarget {
109 enum ZigLLVM_ArchType arch;
110 enum Os os;
111 enum ZigLLVM_EnvironmentType abi;
112
113 bool is_native_os;
114 bool is_native_cpu;
115
116 const char *llvm_cpu_name;
117 const char *llvm_cpu_features;
118 const char *llvm_target_abi;
119};
120
121// ABI warning
122struct Stage2Progress;
123// ABI warning
124struct Stage2ProgressNode;
125
126enum BuildMode {
127 BuildModeDebug,
128 BuildModeSafeRelease,
129 BuildModeFastRelease,
130 BuildModeSmallRelease,
131};
132
133
134struct ZigStage1Pkg {
135 const char *name_ptr;
136 size_t name_len;
137
138 const char *path_ptr;
139 size_t path_len;
140
141 struct ZigStage1Pkg **children_ptr;
142 size_t children_len;
143
144 struct ZigStage1Pkg *parent;
145};
146
147// This struct is used by both main.cpp and stage1.zig.
148struct ZigStage1 {
149 const char *root_name_ptr;
150 size_t root_name_len;
151
152 const char *emit_o_ptr;
153 size_t emit_o_len;
154
155 const char *emit_h_ptr;
156 size_t emit_h_len;
157
158 const char *emit_asm_ptr;
159 size_t emit_asm_len;
160
161 const char *emit_llvm_ir_ptr;
162 size_t emit_llvm_ir_len;
163
164 const char *emit_bitcode_ptr;
165 size_t emit_bitcode_len;
166
167 const char *builtin_zig_path_ptr;
168 size_t builtin_zig_path_len;
169
170 const char *test_filter_ptr;
171 size_t test_filter_len;
172
173 const char *test_name_prefix_ptr;
174 size_t test_name_prefix_len;
175
176 void *userdata;
177 struct ZigStage1Pkg *main_pkg;
178 struct Stage2ProgressNode *main_progress_node;
179
180 enum CodeModel code_model;
181 enum TargetSubsystem subsystem;
182 enum ErrColor err_color;
183
184 bool pic;
185 bool pie;
186 bool lto;
187 bool unwind_tables;
188 bool link_libc;
189 bool link_libcpp;
190 bool strip;
191 bool is_single_threaded;
192 bool dll_export_fns;
193 bool link_mode_dynamic;
194 bool valgrind_enabled;
195 bool tsan_enabled;
196 bool function_sections;
197 bool include_compiler_rt;
198 bool enable_stack_probing;
199 bool red_zone;
200 bool omit_frame_pointer;
201 bool enable_time_report;
202 bool enable_stack_report;
203 bool test_is_evented;
204 bool verbose_ir;
205 bool verbose_llvm_ir;
206 bool verbose_cimport;
207 bool verbose_llvm_cpu_features;
208
209 // Set by stage1
210 bool have_c_main;
211 bool have_winmain;
212 bool have_wwinmain;
213 bool have_winmain_crt_startup;
214 bool have_wwinmain_crt_startup;
215 bool have_dllmain_crt_startup;
216};
217
218ZIG_EXTERN_C void zig_stage1_os_init(void);
219
220ZIG_EXTERN_C struct ZigStage1 *zig_stage1_create(enum BuildMode optimize_mode,
221 const char *main_pkg_path_ptr, size_t main_pkg_path_len,
222 const char *root_src_path_ptr, size_t root_src_path_len,
223 const char *zig_lib_dir_ptr, size_t zig_lib_dir_len,
224 const struct ZigTarget *target, bool is_test_build);
225
226ZIG_EXTERN_C void zig_stage1_build_object(struct ZigStage1 *);
227
228ZIG_EXTERN_C void zig_stage1_destroy(struct ZigStage1 *);
229
230#endif
src/stage1/stage2.h deleted-188
...@@ -1,188 +0,0 @@
1/*
2 * Copyright (c) 2019 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8// This file deals with exposing stage2 Zig code to stage1 C++ code.
9
10#ifndef ZIG_STAGE2_H
11#define ZIG_STAGE2_H
12
13#include <stddef.h>
14#include <stdint.h>
15#include <stdio.h>
16
17#include "stage1.h"
18
19#ifdef __cplusplus
20#define ZIG_EXTERN_C extern "C"
21#else
22#define ZIG_EXTERN_C
23#endif
24
25#if defined(_MSC_VER)
26#define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn)
27#else
28#define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn))
29#endif
30
31// ABI warning: the types and declarations in this file must match both those in
32// stage2.cpp and src/stage1.zig.
33
34// ABI warning
35enum Error {
36 ErrorNone,
37 ErrorNoMem,
38 ErrorInvalidFormat,
39 ErrorSemanticAnalyzeFail,
40 ErrorAccess,
41 ErrorInterrupted,
42 ErrorSystemResources,
43 ErrorFileNotFound,
44 ErrorFileSystem,
45 ErrorFileTooBig,
46 ErrorDivByZero,
47 ErrorOverflow,
48 ErrorPathAlreadyExists,
49 ErrorUnexpected,
50 ErrorExactDivRemainder,
51 ErrorNegativeDenominator,
52 ErrorShiftedOutOneBits,
53 ErrorCCompileErrors,
54 ErrorEndOfFile,
55 ErrorIsDir,
56 ErrorNotDir,
57 ErrorUnsupportedOperatingSystem,
58 ErrorSharingViolation,
59 ErrorPipeBusy,
60 ErrorPrimitiveTypeNotFound,
61 ErrorCacheUnavailable,
62 ErrorPathTooLong,
63 ErrorCCompilerCannotFindFile,
64 ErrorNoCCompilerInstalled,
65 ErrorReadingDepFile,
66 ErrorInvalidDepFile,
67 ErrorMissingArchitecture,
68 ErrorMissingOperatingSystem,
69 ErrorUnknownArchitecture,
70 ErrorUnknownOperatingSystem,
71 ErrorUnknownABI,
72 ErrorInvalidFilename,
73 ErrorDiskQuota,
74 ErrorDiskSpace,
75 ErrorUnexpectedWriteFailure,
76 ErrorUnexpectedSeekFailure,
77 ErrorUnexpectedFileTruncationFailure,
78 ErrorUnimplemented,
79 ErrorOperationAborted,
80 ErrorBrokenPipe,
81 ErrorNoSpaceLeft,
82 ErrorNotLazy,
83 ErrorIsAsync,
84 ErrorImportOutsidePkgPath,
85 ErrorUnknownCpu,
86 ErrorUnknownCpuFeature,
87 ErrorInvalidCpuFeatures,
88 ErrorInvalidLlvmCpuFeaturesFormat,
89 ErrorUnknownApplicationBinaryInterface,
90 ErrorASTUnitFailure,
91 ErrorBadPathName,
92 ErrorSymLinkLoop,
93 ErrorProcessFdQuotaExceeded,
94 ErrorSystemFdQuotaExceeded,
95 ErrorNoDevice,
96 ErrorDeviceBusy,
97 ErrorUnableToSpawnCCompiler,
98 ErrorCCompilerExitCode,
99 ErrorCCompilerCrashed,
100 ErrorCCompilerCannotFindHeaders,
101 ErrorLibCRuntimeNotFound,
102 ErrorLibCStdLibHeaderNotFound,
103 ErrorLibCKernel32LibNotFound,
104 ErrorUnsupportedArchitecture,
105 ErrorWindowsSdkNotFound,
106 ErrorUnknownDynamicLinkerPath,
107 ErrorTargetHasNoDynamicLinker,
108 ErrorInvalidAbiVersion,
109 ErrorInvalidOperatingSystemVersion,
110 ErrorUnknownClangOption,
111 ErrorNestedResponseFile,
112 ErrorZigIsTheCCompiler,
113 ErrorFileBusy,
114 ErrorLocked,
115 ErrorInvalidCharacter,
116 ErrorUnicodePointTooLarge,
117};
118
119// ABI warning
120struct Stage2ErrorMsg {
121 const char *filename_ptr; // can be null
122 size_t filename_len;
123 const char *msg_ptr;
124 size_t msg_len;
125 const char *source; // valid until the ASTUnit is freed. can be null
126 unsigned line; // 0 based
127 unsigned column; // 0 based
128 unsigned offset; // byte offset into source
129};
130
131// ABI warning
132ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
133
134// ABI warning
135ZIG_EXTERN_C struct Stage2Progress *stage2_progress_create(void);
136// ABI warning
137ZIG_EXTERN_C void stage2_progress_disable_tty(struct Stage2Progress *progress);
138// ABI warning
139ZIG_EXTERN_C void stage2_progress_destroy(struct Stage2Progress *progress);
140// ABI warning
141ZIG_EXTERN_C struct Stage2ProgressNode *stage2_progress_start_root(struct Stage2Progress *progress,
142 const char *name_ptr, size_t name_len, size_t estimated_total_items);
143// ABI warning
144ZIG_EXTERN_C struct Stage2ProgressNode *stage2_progress_start(struct Stage2ProgressNode *node,
145 const char *name_ptr, size_t name_len, size_t estimated_total_items);
146// ABI warning
147ZIG_EXTERN_C void stage2_progress_end(struct Stage2ProgressNode *node);
148// ABI warning
149ZIG_EXTERN_C void stage2_progress_complete_one(struct Stage2ProgressNode *node);
150// ABI warning
151ZIG_EXTERN_C void stage2_progress_update_node(struct Stage2ProgressNode *node,
152 size_t completed_count, size_t estimated_total_items);
153
154// ABI warning
155struct Stage2SemVer {
156 uint32_t major;
157 uint32_t minor;
158 uint32_t patch;
159};
160
161// ABI warning
162ZIG_EXTERN_C const char *stage2_version_string(void);
163
164// ABI warning
165ZIG_EXTERN_C Stage2SemVer stage2_version(void);
166
167// ABI warning
168ZIG_EXTERN_C enum Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu,
169 const char *dynamic_linker);
170
171// ABI warning
172ZIG_EXTERN_C const char *stage2_fetch_file(struct ZigStage1 *stage1, const char *path_ptr, size_t path_len,
173 size_t *result_len);
174
175// ABI warning
176ZIG_EXTERN_C Error stage2_cimport(struct ZigStage1 *stage1, const char *c_src_ptr, size_t c_src_len,
177 const char **out_zig_path_ptr, size_t *out_zig_path_len,
178 struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len);
179
180// ABI warning
181ZIG_EXTERN_C const char *stage2_add_link_lib(struct ZigStage1 *stage1,
182 const char *lib_name_ptr, size_t lib_name_len,
183 const char *symbol_name_ptr, size_t symbol_name_len);
184
185// ABI warning
186ZIG_EXTERN_C enum Error stage2_append_symbol(struct ZigStage1 *stage1, const char *name_ptr, size_t name_len);
187
188#endif
src/stage1/target.cpp deleted-1165
...@@ -1,1165 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "buffer.hpp"
9#include "error.hpp"
10#include "target.hpp"
11#include "util.hpp"
12#include "os.hpp"
13
14#include <stdio.h>
15
16static const ZigLLVM_ArchType arch_list[] = {
17 ZigLLVM_arm, // ARM (little endian): arm, armv.*, xscale
18 ZigLLVM_armeb, // ARM (big endian): armeb
19 ZigLLVM_aarch64, // AArch64 (little endian): aarch64
20 ZigLLVM_aarch64_be, // AArch64 (big endian): aarch64_be
21 ZigLLVM_aarch64_32, // AArch64 (little endian) ILP32: aarch64_32
22 ZigLLVM_arc, // ARC: Synopsys ARC
23 ZigLLVM_avr, // AVR: Atmel AVR microcontroller
24 ZigLLVM_bpfel, // eBPF or extended BPF or 64-bit BPF (little endian)
25 ZigLLVM_bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
26 ZigLLVM_csky, // CSKY: csky
27 ZigLLVM_dxil, // DXIL 32-bit DirectX bytecode
28 ZigLLVM_hexagon, // Hexagon: hexagon
29 ZigLLVM_loongarch32, // LoongArch (32-bit): loongarch32
30 ZigLLVM_loongarch64, // LoongArch (64-bit): loongarch64
31 ZigLLVM_m68k, // M68k: Motorola 680x0 family
32 ZigLLVM_mips, // MIPS: mips, mipsallegrex, mipsr6
33 ZigLLVM_mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el
34 ZigLLVM_mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6
35 ZigLLVM_mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el
36 ZigLLVM_msp430, // MSP430: msp430
37 ZigLLVM_ppc, // PPC: powerpc
38 ZigLLVM_ppcle, // PPCLE: powerpc (little endian)
39 ZigLLVM_ppc64, // PPC64: powerpc64, ppu
40 ZigLLVM_ppc64le, // PPC64LE: powerpc64le
41 ZigLLVM_r600, // R600: AMD GPUs HD2XXX - HD6XXX
42 ZigLLVM_amdgcn, // AMDGCN: AMD GCN GPUs
43 ZigLLVM_riscv32, // RISC-V (32-bit): riscv32
44 ZigLLVM_riscv64, // RISC-V (64-bit): riscv64
45 ZigLLVM_sparc, // Sparc: sparc
46 ZigLLVM_sparcv9, // Sparcv9: Sparcv9
47 ZigLLVM_sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
48 ZigLLVM_systemz, // SystemZ: s390x
49 ZigLLVM_tce, // TCE (http://tce.cs.tut.fi/): tce
50 ZigLLVM_tcele, // TCE little endian (http://tce.cs.tut.fi/): tcele
51 ZigLLVM_thumb, // Thumb (little endian): thumb, thumbv.*
52 ZigLLVM_thumbeb, // Thumb (big endian): thumbeb
53 ZigLLVM_x86, // X86: i[3-9]86
54 ZigLLVM_x86_64, // X86-64: amd64, x86_64
55 ZigLLVM_xcore, // XCore: xcore
56 ZigLLVM_nvptx, // NVPTX: 32-bit
57 ZigLLVM_nvptx64, // NVPTX: 64-bit
58 ZigLLVM_le32, // le32: generic little-endian 32-bit CPU (PNaCl)
59 ZigLLVM_le64, // le64: generic little-endian 64-bit CPU (PNaCl)
60 ZigLLVM_amdil, // AMDIL
61 ZigLLVM_amdil64, // AMDIL with 64-bit pointers
62 ZigLLVM_hsail, // AMD HSAIL
63 ZigLLVM_hsail64, // AMD HSAIL with 64-bit pointers
64 ZigLLVM_spir, // SPIR: standard portable IR for OpenCL 32-bit version
65 ZigLLVM_spir64, // SPIR: standard portable IR for OpenCL 64-bit version
66 ZigLLVM_spirv32, // SPIR-V with 32-bit pointers
67 ZigLLVM_spirv64, // SPIR-V with 64-bit pointers
68 ZigLLVM_kalimba, // Kalimba: generic kalimba
69 ZigLLVM_shave, // SHAVE: Movidius vector VLIW processors
70 ZigLLVM_lanai, // Lanai: Lanai 32-bit
71 ZigLLVM_wasm32, // WebAssembly with 32-bit pointers
72 ZigLLVM_wasm64, // WebAssembly with 64-bit pointers
73 ZigLLVM_renderscript32, // 32-bit RenderScript
74 ZigLLVM_renderscript64, // 64-bit RenderScript
75 ZigLLVM_ve, // NEC SX-Aurora Vector Engine
76};
77
78static const ZigLLVM_VendorType vendor_list[] = {
79 ZigLLVM_Apple,
80 ZigLLVM_PC,
81 ZigLLVM_SCEI,
82 ZigLLVM_Freescale,
83 ZigLLVM_IBM,
84 ZigLLVM_ImaginationTechnologies,
85 ZigLLVM_MipsTechnologies,
86 ZigLLVM_NVIDIA,
87 ZigLLVM_CSR,
88 ZigLLVM_Myriad,
89 ZigLLVM_AMD,
90 ZigLLVM_Mesa,
91 ZigLLVM_SUSE,
92};
93
94static const Os os_list[] = {
95 OsFreestanding,
96 OsAnanas,
97 OsCloudABI,
98 OsDragonFly,
99 OsFreeBSD,
100 OsFuchsia,
101 OsIOS,
102 OsKFreeBSD,
103 OsLinux,
104 OsLv2, // PS3
105 OsMacOSX,
106 OsNetBSD,
107 OsOpenBSD,
108 OsSolaris,
109 OsWindows,
110 OsZOS,
111 OsHaiku,
112 OsMinix,
113 OsRTEMS,
114 OsNaCl, // Native Client
115 OsAIX,
116 OsCUDA, // NVIDIA CUDA
117 OsNVCL, // NVIDIA OpenCL
118 OsAMDHSA, // AMD HSA Runtime
119 OsPS4,
120 OsPS5,
121 OsELFIAMCU,
122 OsTvOS, // Apple tvOS
123 OsWatchOS, // Apple watchOS
124 OsDriverKit, // Apple DriverKit
125 OsMesa3D,
126 OsContiki,
127 OsAMDPAL,
128 OsHermitCore,
129 OsHurd,
130 OsWASI,
131 OsEmscripten,
132 OsShaderModel, // DirectX ShaderModel
133 OsUefi,
134 OsOpenCL,
135 OsGLSL450,
136 OsVulkan,
137 OsPlan9,
138 OsOther,
139};
140
141// Coordinate with zig_llvm.h
142static const ZigLLVM_EnvironmentType abi_list[] = {
143 ZigLLVM_UnknownEnvironment,
144
145 ZigLLVM_GNU,
146 ZigLLVM_GNUABIN32,
147 ZigLLVM_GNUABI64,
148 ZigLLVM_GNUEABI,
149 ZigLLVM_GNUEABIHF,
150 ZigLLVM_GNUX32,
151 ZigLLVM_GNUILP32,
152 ZigLLVM_CODE16,
153 ZigLLVM_EABI,
154 ZigLLVM_EABIHF,
155 ZigLLVM_Android,
156 ZigLLVM_Musl,
157 ZigLLVM_MuslEABI,
158 ZigLLVM_MuslEABIHF,
159 ZigLLVM_MuslX32,
160
161 ZigLLVM_MSVC,
162 ZigLLVM_Itanium,
163 ZigLLVM_Cygnus,
164 ZigLLVM_CoreCLR,
165 ZigLLVM_Simulator, // Simulator variants of other systems, e.g., Apple's iOS
166 ZigLLVM_MacABI, // Mac Catalyst variant of Apple's iOS deployment target.
167
168 ZigLLVM_Pixel,
169 ZigLLVM_Vertex,
170 ZigLLVM_Geometry,
171 ZigLLVM_Hull,
172 ZigLLVM_Domain,
173 ZigLLVM_Compute,
174 ZigLLVM_Library,
175 ZigLLVM_RayGeneration,
176 ZigLLVM_Intersection,
177 ZigLLVM_AnyHit,
178 ZigLLVM_ClosestHit,
179 ZigLLVM_Miss,
180 ZigLLVM_Callable,
181 ZigLLVM_Mesh,
182 ZigLLVM_Amplification,
183};
184
185static const ZigLLVM_ObjectFormatType oformat_list[] = {
186 ZigLLVM_UnknownObjectFormat,
187 ZigLLVM_COFF,
188 ZigLLVM_DXContainer,
189 ZigLLVM_ELF,
190 ZigLLVM_GOFF,
191 ZigLLVM_MachO,
192 ZigLLVM_SPIRV,
193 ZigLLVM_Wasm,
194 ZigLLVM_XCOFF,
195};
196
197size_t target_oformat_count(void) {
198 return array_length(oformat_list);
199}
200
201ZigLLVM_ObjectFormatType target_oformat_enum(size_t index) {
202 assert(index < array_length(oformat_list));
203 return oformat_list[index];
204}
205
206const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat) {
207 switch (oformat) {
208 case ZigLLVM_UnknownObjectFormat: return "unknown";
209 case ZigLLVM_COFF: return "coff";
210 case ZigLLVM_DXContainer: return "dxcontainer";
211 case ZigLLVM_ELF: return "elf";
212 case ZigLLVM_GOFF: return "goff";
213 case ZigLLVM_MachO: return "macho";
214 case ZigLLVM_SPIRV: return "spirv";
215 case ZigLLVM_Wasm: return "wasm";
216 case ZigLLVM_XCOFF: return "xcoff";
217 }
218 zig_unreachable();
219}
220
221size_t target_arch_count(void) {
222 return array_length(arch_list);
223}
224
225ZigLLVM_ArchType target_arch_enum(size_t index) {
226 assert(index < array_length(arch_list));
227 return arch_list[index];
228}
229
230size_t target_vendor_count(void) {
231 return array_length(vendor_list);
232}
233
234ZigLLVM_VendorType target_vendor_enum(size_t index) {
235 assert(index < array_length(vendor_list));
236 return vendor_list[index];
237}
238
239size_t target_os_count(void) {
240 return array_length(os_list);
241}
242Os target_os_enum(size_t index) {
243 assert(index < array_length(os_list));
244 return os_list[index];
245}
246
247ZigLLVM_OSType get_llvm_os_type(Os os_type) {
248 switch (os_type) {
249 case OsFreestanding:
250 case OsOpenCL:
251 case OsGLSL450:
252 case OsVulkan:
253 case OsPlan9:
254 case OsOther:
255 return ZigLLVM_UnknownOS;
256 case OsAnanas:
257 return ZigLLVM_Ananas;
258 case OsCloudABI:
259 return ZigLLVM_CloudABI;
260 case OsDragonFly:
261 return ZigLLVM_DragonFly;
262 case OsFreeBSD:
263 return ZigLLVM_FreeBSD;
264 case OsFuchsia:
265 return ZigLLVM_Fuchsia;
266 case OsIOS:
267 return ZigLLVM_IOS;
268 case OsKFreeBSD:
269 return ZigLLVM_KFreeBSD;
270 case OsLinux:
271 return ZigLLVM_Linux;
272 case OsLv2:
273 return ZigLLVM_Lv2;
274 case OsMacOSX:
275 return ZigLLVM_MacOSX;
276 case OsNetBSD:
277 return ZigLLVM_NetBSD;
278 case OsOpenBSD:
279 return ZigLLVM_OpenBSD;
280 case OsSolaris:
281 return ZigLLVM_Solaris;
282 case OsWindows:
283 case OsUefi:
284 return ZigLLVM_Win32;
285 case OsZOS:
286 return ZigLLVM_ZOS;
287 case OsHaiku:
288 return ZigLLVM_Haiku;
289 case OsMinix:
290 return ZigLLVM_Minix;
291 case OsRTEMS:
292 return ZigLLVM_RTEMS;
293 case OsNaCl:
294 return ZigLLVM_NaCl;
295 case OsAIX:
296 return ZigLLVM_AIX;
297 case OsCUDA:
298 return ZigLLVM_CUDA;
299 case OsNVCL:
300 return ZigLLVM_NVCL;
301 case OsAMDHSA:
302 return ZigLLVM_AMDHSA;
303 case OsPS4:
304 return ZigLLVM_PS4;
305 case OsPS5:
306 return ZigLLVM_PS5;
307 case OsELFIAMCU:
308 return ZigLLVM_ELFIAMCU;
309 case OsTvOS:
310 return ZigLLVM_TvOS;
311 case OsWatchOS:
312 return ZigLLVM_WatchOS;
313 case OsDriverKit:
314 return ZigLLVM_DriverKit;
315 case OsMesa3D:
316 return ZigLLVM_Mesa3D;
317 case OsContiki:
318 return ZigLLVM_Contiki;
319 case OsAMDPAL:
320 return ZigLLVM_AMDPAL;
321 case OsHermitCore:
322 return ZigLLVM_HermitCore;
323 case OsHurd:
324 return ZigLLVM_Hurd;
325 case OsWASI:
326 return ZigLLVM_WASI;
327 case OsEmscripten:
328 return ZigLLVM_Emscripten;
329 case OsShaderModel:
330 return ZigLLVM_ShaderModel;
331 }
332 zig_unreachable();
333}
334
335const char *target_os_name(Os os_type) {
336 switch (os_type) {
337 case OsFreestanding:
338 return "freestanding";
339 case OsPlan9:
340 return "plan9";
341 case OsUefi:
342 return "uefi";
343 case OsOther:
344 return "other";
345 case OsAnanas:
346 case OsCloudABI:
347 case OsDragonFly:
348 case OsFreeBSD:
349 case OsFuchsia:
350 case OsIOS:
351 case OsKFreeBSD:
352 case OsLinux:
353 case OsLv2: // PS3
354 case OsMacOSX:
355 case OsNetBSD:
356 case OsOpenBSD:
357 case OsSolaris:
358 case OsWindows:
359 case OsZOS:
360 case OsHaiku:
361 case OsMinix:
362 case OsRTEMS:
363 case OsNaCl: // Native Client
364 case OsAIX:
365 case OsCUDA: // NVIDIA CUDA
366 case OsNVCL: // NVIDIA OpenCL
367 case OsAMDHSA: // AMD HSA Runtime
368 case OsPS4:
369 case OsPS5:
370 case OsELFIAMCU:
371 case OsTvOS: // Apple tvOS
372 case OsWatchOS: // Apple watchOS
373 case OsDriverKit:
374 case OsMesa3D:
375 case OsContiki:
376 case OsAMDPAL:
377 case OsHermitCore:
378 case OsHurd:
379 case OsWASI:
380 case OsEmscripten:
381 case OsShaderModel:
382 case OsOpenCL:
383 case OsGLSL450:
384 case OsVulkan:
385 return ZigLLVMGetOSTypeName(get_llvm_os_type(os_type));
386 }
387 zig_unreachable();
388}
389
390size_t target_abi_count(void) {
391 return array_length(abi_list);
392}
393ZigLLVM_EnvironmentType target_abi_enum(size_t index) {
394 assert(index < array_length(abi_list));
395 return abi_list[index];
396}
397const char *target_abi_name(ZigLLVM_EnvironmentType abi) {
398 if (abi == ZigLLVM_UnknownEnvironment)
399 return "none";
400 return ZigLLVMGetEnvironmentTypeName(abi);
401}
402
403Error target_parse_arch(ZigLLVM_ArchType *out_arch, const char *arch_ptr, size_t arch_len) {
404 *out_arch = ZigLLVM_UnknownArch;
405 for (size_t arch_i = 0; arch_i < array_length(arch_list); arch_i += 1) {
406 ZigLLVM_ArchType arch = arch_list[arch_i];
407 if (mem_eql_str(arch_ptr, arch_len, target_arch_name(arch))) {
408 *out_arch = arch;
409 return ErrorNone;
410 }
411 }
412 return ErrorUnknownArchitecture;
413}
414
415Error target_parse_os(Os *out_os, const char *os_ptr, size_t os_len) {
416 if (mem_eql_str(os_ptr, os_len, "native")) {
417#if defined(ZIG_OS_DARWIN)
418 *out_os = OsMacOSX;
419 return ErrorNone;
420#elif defined(ZIG_OS_WINDOWS)
421 *out_os = OsWindows;
422 return ErrorNone;
423#elif defined(ZIG_OS_LINUX)
424 *out_os = OsLinux;
425 return ErrorNone;
426#elif defined(ZIG_OS_FREEBSD)
427 *out_os = OsFreeBSD;
428 return ErrorNone;
429#elif defined(ZIG_OS_NETBSD)
430 *out_os = OsNetBSD;
431 return ErrorNone;
432#elif defined(ZIG_OS_DRAGONFLY)
433 *out_os = OsDragonFly;
434 return ErrorNone;
435#elif defined(ZIG_OS_OPENBSD)
436 *out_os = OsOpenBSD;
437 return ErrorNone;
438#elif defined(ZIG_OS_HAIKU)
439 *out_os = OsHaiku;
440 return ErrorNone;
441#elif defined(ZIG_OS_SOLARIS)
442 *out_os = OsSolaris;
443 return ErrorNone;
444#else
445 zig_panic("stage1 is unable to detect native target for this OS");
446#endif
447 }
448
449 for (size_t i = 0; i < array_length(os_list); i += 1) {
450 Os os = os_list[i];
451 const char *os_name = target_os_name(os);
452 if (mem_eql_str(os_ptr, os_len, os_name)) {
453 *out_os = os;
454 return ErrorNone;
455 }
456 }
457 return ErrorUnknownOperatingSystem;
458}
459
460Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, size_t abi_len) {
461 for (size_t i = 0; i < array_length(abi_list); i += 1) {
462 ZigLLVM_EnvironmentType abi = abi_list[i];
463 const char *abi_name = target_abi_name(abi);
464 if (mem_eql_str(abi_ptr, abi_len, abi_name)) {
465 *out_abi = abi;
466 return ErrorNone;
467 }
468 }
469 return ErrorUnknownABI;
470}
471
472const char *target_arch_name(ZigLLVM_ArchType arch) {
473 return ZigLLVMGetArchTypeName(arch);
474}
475
476void init_all_targets(void) {
477 LLVMInitializeAllTargets();
478 LLVMInitializeAllTargetInfos();
479 LLVMInitializeAllTargetMCs();
480 LLVMInitializeAllAsmPrinters();
481 LLVMInitializeAllAsmParsers();
482}
483
484void target_triple_zig(Buf *triple, const ZigTarget *target) {
485 buf_resize(triple, 0);
486 buf_appendf(triple, "%s-%s-%s",
487 target_arch_name(target->arch),
488 target_os_name(target->os),
489 target_abi_name(target->abi));
490}
491
492void target_triple_llvm(Buf *triple, const ZigTarget *target) {
493 buf_resize(triple, 0);
494 buf_appendf(triple, "%s-%s-%s-%s",
495 ZigLLVMGetArchTypeName(target->arch),
496 ZigLLVMGetVendorTypeName(ZigLLVM_UnknownVendor),
497 ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)),
498 ZigLLVMGetEnvironmentTypeName(target->abi));
499}
500
501bool target_os_is_darwin(Os os) {
502 switch (os) {
503 case OsMacOSX:
504 case OsIOS:
505 case OsWatchOS:
506 case OsTvOS:
507 return true;
508 default:
509 return false;
510 }
511}
512
513ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target) {
514 if (target->os == OsUefi || target->os == OsWindows) {
515 return ZigLLVM_COFF;
516 } else if (target_os_is_darwin(target->os)) {
517 return ZigLLVM_MachO;
518 }
519 if (target->arch == ZigLLVM_wasm32 ||
520 target->arch == ZigLLVM_wasm64)
521 {
522 return ZigLLVM_Wasm;
523 }
524 return ZigLLVM_ELF;
525}
526
527// See lib/Support/Triple.cpp in LLVM for the source of this data.
528// getArchPointerBitWidth
529uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) {
530 switch (arch) {
531 case ZigLLVM_UnknownArch:
532 return 0;
533
534 case ZigLLVM_avr:
535 case ZigLLVM_msp430:
536 return 16;
537
538 case ZigLLVM_arc:
539 case ZigLLVM_arm:
540 case ZigLLVM_armeb:
541 case ZigLLVM_hexagon:
542 case ZigLLVM_m68k:
543 case ZigLLVM_le32:
544 case ZigLLVM_mips:
545 case ZigLLVM_mipsel:
546 case ZigLLVM_nvptx:
547 case ZigLLVM_ppc:
548 case ZigLLVM_ppcle:
549 case ZigLLVM_r600:
550 case ZigLLVM_riscv32:
551 case ZigLLVM_sparc:
552 case ZigLLVM_sparcel:
553 case ZigLLVM_tce:
554 case ZigLLVM_tcele:
555 case ZigLLVM_thumb:
556 case ZigLLVM_thumbeb:
557 case ZigLLVM_x86:
558 case ZigLLVM_xcore:
559 case ZigLLVM_amdil:
560 case ZigLLVM_hsail:
561 case ZigLLVM_spir:
562 case ZigLLVM_kalimba:
563 case ZigLLVM_lanai:
564 case ZigLLVM_shave:
565 case ZigLLVM_wasm32:
566 case ZigLLVM_renderscript32:
567 case ZigLLVM_aarch64_32:
568 case ZigLLVM_csky:
569 case ZigLLVM_spirv32:
570 case ZigLLVM_loongarch32:
571 case ZigLLVM_dxil:
572 return 32;
573
574 case ZigLLVM_aarch64:
575 case ZigLLVM_aarch64_be:
576 case ZigLLVM_amdgcn:
577 case ZigLLVM_bpfel:
578 case ZigLLVM_bpfeb:
579 case ZigLLVM_le64:
580 case ZigLLVM_mips64:
581 case ZigLLVM_mips64el:
582 case ZigLLVM_nvptx64:
583 case ZigLLVM_ppc64:
584 case ZigLLVM_ppc64le:
585 case ZigLLVM_riscv64:
586 case ZigLLVM_sparcv9:
587 case ZigLLVM_systemz:
588 case ZigLLVM_x86_64:
589 case ZigLLVM_amdil64:
590 case ZigLLVM_hsail64:
591 case ZigLLVM_spir64:
592 case ZigLLVM_wasm64:
593 case ZigLLVM_renderscript64:
594 case ZigLLVM_ve:
595 case ZigLLVM_spirv64:
596 case ZigLLVM_loongarch64:
597 return 64;
598 }
599 zig_unreachable();
600}
601
602uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch) {
603 switch (arch) {
604 case ZigLLVM_UnknownArch:
605 zig_unreachable();
606
607 case ZigLLVM_avr:
608 case ZigLLVM_msp430:
609 return 16;
610
611 case ZigLLVM_arc:
612 case ZigLLVM_arm:
613 case ZigLLVM_armeb:
614 case ZigLLVM_hexagon:
615 case ZigLLVM_m68k:
616 case ZigLLVM_le32:
617 case ZigLLVM_mips:
618 case ZigLLVM_mipsel:
619 case ZigLLVM_nvptx:
620 case ZigLLVM_ppc:
621 case ZigLLVM_ppcle:
622 case ZigLLVM_r600:
623 case ZigLLVM_riscv32:
624 case ZigLLVM_sparc:
625 case ZigLLVM_sparcel:
626 case ZigLLVM_tce:
627 case ZigLLVM_tcele:
628 case ZigLLVM_thumb:
629 case ZigLLVM_thumbeb:
630 case ZigLLVM_x86:
631 case ZigLLVM_xcore:
632 case ZigLLVM_amdil:
633 case ZigLLVM_hsail:
634 case ZigLLVM_spir:
635 case ZigLLVM_kalimba:
636 case ZigLLVM_lanai:
637 case ZigLLVM_shave:
638 case ZigLLVM_wasm32:
639 case ZigLLVM_renderscript32:
640 case ZigLLVM_csky:
641 case ZigLLVM_spirv32:
642 case ZigLLVM_loongarch32:
643 case ZigLLVM_dxil:
644 return 32;
645
646 case ZigLLVM_aarch64:
647 case ZigLLVM_aarch64_be:
648 case ZigLLVM_aarch64_32:
649 case ZigLLVM_amdgcn:
650 case ZigLLVM_bpfel:
651 case ZigLLVM_bpfeb:
652 case ZigLLVM_le64:
653 case ZigLLVM_mips64:
654 case ZigLLVM_mips64el:
655 case ZigLLVM_nvptx64:
656 case ZigLLVM_ppc64:
657 case ZigLLVM_ppc64le:
658 case ZigLLVM_riscv64:
659 case ZigLLVM_sparcv9:
660 case ZigLLVM_systemz:
661 case ZigLLVM_amdil64:
662 case ZigLLVM_hsail64:
663 case ZigLLVM_spir64:
664 case ZigLLVM_wasm64:
665 case ZigLLVM_renderscript64:
666 case ZigLLVM_ve:
667 case ZigLLVM_spirv64:
668 case ZigLLVM_loongarch64:
669 return 64;
670
671 case ZigLLVM_x86_64:
672 return 128;
673 }
674 zig_unreachable();
675}
676
677uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
678 switch (target->os) {
679 case OsFreestanding:
680 case OsOther:
681 switch (target->arch) {
682 case ZigLLVM_msp430:
683 switch (id) {
684 case CIntTypeShort:
685 case CIntTypeUShort:
686 return 16;
687 case CIntTypeInt:
688 case CIntTypeUInt:
689 return 16;
690 case CIntTypeLong:
691 case CIntTypeULong:
692 return 32;
693 case CIntTypeLongLong:
694 case CIntTypeULongLong:
695 return 64;
696 case CIntTypeCount:
697 zig_unreachable();
698 }
699 zig_unreachable();
700 default:
701 switch (id) {
702 case CIntTypeShort:
703 case CIntTypeUShort:
704 return 16;
705 case CIntTypeInt:
706 case CIntTypeUInt:
707 return 32;
708 case CIntTypeLong:
709 case CIntTypeULong:
710 return target_arch_pointer_bit_width(target->arch);
711 case CIntTypeLongLong:
712 case CIntTypeULongLong:
713 return 64;
714 case CIntTypeCount:
715 zig_unreachable();
716 }
717 }
718 zig_unreachable();
719 case OsLinux:
720 case OsMacOSX:
721 case OsFreeBSD:
722 case OsNetBSD:
723 case OsDragonFly:
724 case OsOpenBSD:
725 case OsWASI:
726 case OsHaiku:
727 case OsSolaris:
728 case OsEmscripten:
729 case OsPlan9:
730 case OsCUDA:
731 case OsNVCL:
732 switch (id) {
733 case CIntTypeShort:
734 case CIntTypeUShort:
735 return 16;
736 case CIntTypeInt:
737 case CIntTypeUInt:
738 return 32;
739 case CIntTypeLong:
740 case CIntTypeULong:
741 return target_arch_pointer_bit_width(target->arch);
742 case CIntTypeLongLong:
743 case CIntTypeULongLong:
744 return 64;
745 case CIntTypeCount:
746 zig_unreachable();
747 }
748 zig_unreachable();
749 case OsUefi:
750 case OsWindows:
751 switch (id) {
752 case CIntTypeShort:
753 case CIntTypeUShort:
754 return 16;
755 case CIntTypeInt:
756 case CIntTypeUInt:
757 case CIntTypeLong:
758 case CIntTypeULong:
759 return 32;
760 case CIntTypeLongLong:
761 case CIntTypeULongLong:
762 return 64;
763 case CIntTypeCount:
764 zig_unreachable();
765 }
766 zig_unreachable();
767 case OsIOS:
768 switch (id) {
769 case CIntTypeShort:
770 case CIntTypeUShort:
771 return 16;
772 case CIntTypeInt:
773 case CIntTypeUInt:
774 return 32;
775 case CIntTypeLong:
776 case CIntTypeULong:
777 case CIntTypeLongLong:
778 case CIntTypeULongLong:
779 return 64;
780 case CIntTypeCount:
781 zig_unreachable();
782 }
783 zig_unreachable();
784 case OsAnanas:
785 case OsCloudABI:
786 case OsKFreeBSD:
787 case OsLv2:
788 case OsZOS:
789 case OsMinix:
790 case OsRTEMS:
791 case OsNaCl:
792 case OsAIX:
793 case OsAMDHSA:
794 case OsPS4:
795 case OsPS5:
796 case OsELFIAMCU:
797 case OsTvOS:
798 case OsWatchOS:
799 case OsMesa3D:
800 case OsFuchsia:
801 case OsContiki:
802 case OsAMDPAL:
803 case OsHermitCore:
804 case OsHurd:
805 case OsOpenCL:
806 case OsGLSL450:
807 case OsVulkan:
808 case OsDriverKit:
809 case OsShaderModel:
810 zig_panic("TODO c type size in bits for this target");
811 }
812 zig_unreachable();
813}
814
815bool target_allows_addr_zero(const ZigTarget *target) {
816 return target->os == OsFreestanding || target->os == OsUefi;
817}
818
819const char *target_o_file_ext(const ZigTarget *target) {
820 if (target->abi == ZigLLVM_MSVC ||
821 target->os == OsWindows || target->os == OsUefi)
822 {
823 return ".obj";
824 } else {
825 return ".o";
826 }
827}
828
829const char *target_asm_file_ext(const ZigTarget *target) {
830 return ".s";
831}
832
833const char *target_llvm_ir_file_ext(const ZigTarget *target) {
834 return ".ll";
835}
836
837bool target_is_android(const ZigTarget *target) {
838 return target->abi == ZigLLVM_Android;
839}
840
841const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {
842 switch (arch) {
843 case ZigLLVM_UnknownArch:
844 zig_unreachable();
845 case ZigLLVM_x86:
846 return "esp";
847 case ZigLLVM_x86_64:
848 return "rsp";
849 case ZigLLVM_arm:
850 case ZigLLVM_armeb:
851 case ZigLLVM_thumb:
852 case ZigLLVM_thumbeb:
853 case ZigLLVM_aarch64:
854 case ZigLLVM_aarch64_be:
855 case ZigLLVM_aarch64_32:
856 case ZigLLVM_riscv32:
857 case ZigLLVM_riscv64:
858 case ZigLLVM_m68k:
859 case ZigLLVM_mips:
860 case ZigLLVM_mipsel:
861 case ZigLLVM_ppc:
862 case ZigLLVM_ppcle:
863 case ZigLLVM_ppc64:
864 case ZigLLVM_ppc64le:
865 return "sp";
866
867 case ZigLLVM_wasm32:
868 case ZigLLVM_wasm64:
869 case ZigLLVM_spirv32:
870 case ZigLLVM_spirv64:
871 return nullptr; // known to be not available
872
873 case ZigLLVM_amdgcn:
874 case ZigLLVM_amdil:
875 case ZigLLVM_amdil64:
876 case ZigLLVM_arc:
877 case ZigLLVM_avr:
878 case ZigLLVM_bpfeb:
879 case ZigLLVM_bpfel:
880 case ZigLLVM_csky:
881 case ZigLLVM_hexagon:
882 case ZigLLVM_lanai:
883 case ZigLLVM_hsail:
884 case ZigLLVM_hsail64:
885 case ZigLLVM_kalimba:
886 case ZigLLVM_le32:
887 case ZigLLVM_le64:
888 case ZigLLVM_mips64:
889 case ZigLLVM_mips64el:
890 case ZigLLVM_msp430:
891 case ZigLLVM_nvptx:
892 case ZigLLVM_nvptx64:
893 case ZigLLVM_r600:
894 case ZigLLVM_renderscript32:
895 case ZigLLVM_renderscript64:
896 case ZigLLVM_shave:
897 case ZigLLVM_sparc:
898 case ZigLLVM_sparcel:
899 case ZigLLVM_sparcv9:
900 case ZigLLVM_spir:
901 case ZigLLVM_spir64:
902 case ZigLLVM_systemz:
903 case ZigLLVM_tce:
904 case ZigLLVM_tcele:
905 case ZigLLVM_xcore:
906 case ZigLLVM_ve:
907 case ZigLLVM_dxil:
908 case ZigLLVM_loongarch32:
909 case ZigLLVM_loongarch64:
910 zig_panic("TODO populate this table with stack pointer register name for this CPU architecture");
911 }
912 zig_unreachable();
913}
914
915bool target_is_arm(const ZigTarget *target) {
916 switch (target->arch) {
917 case ZigLLVM_UnknownArch:
918 zig_unreachable();
919 case ZigLLVM_aarch64:
920 case ZigLLVM_aarch64_be:
921 case ZigLLVM_aarch64_32:
922 case ZigLLVM_arm:
923 case ZigLLVM_armeb:
924 case ZigLLVM_thumb:
925 case ZigLLVM_thumbeb:
926 return true;
927
928 case ZigLLVM_x86:
929 case ZigLLVM_x86_64:
930 case ZigLLVM_amdgcn:
931 case ZigLLVM_amdil:
932 case ZigLLVM_amdil64:
933 case ZigLLVM_arc:
934 case ZigLLVM_avr:
935 case ZigLLVM_bpfeb:
936 case ZigLLVM_bpfel:
937 case ZigLLVM_csky:
938 case ZigLLVM_hexagon:
939 case ZigLLVM_m68k:
940 case ZigLLVM_lanai:
941 case ZigLLVM_hsail:
942 case ZigLLVM_hsail64:
943 case ZigLLVM_kalimba:
944 case ZigLLVM_le32:
945 case ZigLLVM_le64:
946 case ZigLLVM_mips:
947 case ZigLLVM_mips64:
948 case ZigLLVM_mips64el:
949 case ZigLLVM_mipsel:
950 case ZigLLVM_msp430:
951 case ZigLLVM_nvptx:
952 case ZigLLVM_nvptx64:
953 case ZigLLVM_r600:
954 case ZigLLVM_renderscript32:
955 case ZigLLVM_renderscript64:
956 case ZigLLVM_riscv32:
957 case ZigLLVM_riscv64:
958 case ZigLLVM_shave:
959 case ZigLLVM_sparc:
960 case ZigLLVM_sparcel:
961 case ZigLLVM_sparcv9:
962 case ZigLLVM_spir:
963 case ZigLLVM_spir64:
964 case ZigLLVM_systemz:
965 case ZigLLVM_tce:
966 case ZigLLVM_tcele:
967 case ZigLLVM_wasm32:
968 case ZigLLVM_wasm64:
969 case ZigLLVM_xcore:
970 case ZigLLVM_ppc:
971 case ZigLLVM_ppcle:
972 case ZigLLVM_ppc64:
973 case ZigLLVM_ppc64le:
974 case ZigLLVM_ve:
975 case ZigLLVM_spirv32:
976 case ZigLLVM_spirv64:
977 case ZigLLVM_dxil:
978 case ZigLLVM_loongarch32:
979 case ZigLLVM_loongarch64:
980 return false;
981 }
982 zig_unreachable();
983}
984
985// Valgrind supports more, but Zig does not support them yet.
986bool target_has_valgrind_support(const ZigTarget *target) {
987 switch (target->arch) {
988 case ZigLLVM_UnknownArch:
989 zig_unreachable();
990 case ZigLLVM_x86_64:
991 return (target->os == OsLinux || target->os == OsSolaris ||
992 (target->os == OsWindows && target->abi != ZigLLVM_MSVC));
993 default:
994 return false;
995 }
996 zig_unreachable();
997}
998
999bool target_is_wasm(const ZigTarget *target) {
1000 return target->arch == ZigLLVM_wasm32 || target->arch == ZigLLVM_wasm64;
1001}
1002
1003bool target_is_bpf(const ZigTarget *target) {
1004 return target->arch == ZigLLVM_bpfel || target->arch == ZigLLVM_bpfeb;
1005}
1006
1007ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) {
1008 if (arch == ZigLLVM_wasm32 || arch == ZigLLVM_wasm64) {
1009 return ZigLLVM_Musl;
1010 }
1011 switch (os) {
1012 case OsFreestanding:
1013 case OsAnanas:
1014 case OsCloudABI:
1015 case OsLv2:
1016 case OsSolaris:
1017 case OsZOS:
1018 case OsMinix:
1019 case OsRTEMS:
1020 case OsNaCl:
1021 case OsAIX:
1022 case OsCUDA:
1023 case OsNVCL:
1024 case OsAMDHSA:
1025 case OsPS4:
1026 case OsPS5:
1027 case OsELFIAMCU:
1028 case OsMesa3D:
1029 case OsContiki:
1030 case OsAMDPAL:
1031 case OsHermitCore:
1032 case OsOther:
1033 return ZigLLVM_EABI;
1034 case OsOpenBSD:
1035 case OsFreeBSD:
1036 case OsFuchsia:
1037 case OsKFreeBSD:
1038 case OsNetBSD:
1039 case OsDragonFly:
1040 case OsHurd:
1041 case OsHaiku:
1042 return ZigLLVM_GNU;
1043 case OsUefi:
1044 case OsWindows:
1045 return ZigLLVM_MSVC;
1046 case OsLinux:
1047 case OsWASI:
1048 case OsEmscripten:
1049 return ZigLLVM_Musl;
1050 case OsOpenCL:
1051 case OsGLSL450:
1052 case OsVulkan:
1053 case OsPlan9:
1054 case OsMacOSX:
1055 case OsIOS:
1056 case OsTvOS:
1057 case OsWatchOS:
1058 case OsDriverKit:
1059 case OsShaderModel:
1060 return ZigLLVM_UnknownEnvironment;
1061 }
1062 zig_unreachable();
1063}
1064
1065bool target_has_debug_info(const ZigTarget *target) {
1066 return true;
1067}
1068
1069bool target_long_double_is_f128(const ZigTarget *target) {
1070 if (target->abi == ZigLLVM_MSVC) {
1071 return false;
1072 }
1073 switch (target->arch) {
1074 case ZigLLVM_aarch64:
1075 // According to Apple's official guide:
1076 // > The long double type is a double precision IEEE754 binary floating-point type,
1077 // > which makes it identical to the double type. This behavior contrasts to the
1078 // > standard specification, in which a long double is a quad-precision, IEEE754
1079 // > binary, floating-point type.
1080 // https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms
1081 return !target_os_is_darwin(target->os);
1082
1083 case ZigLLVM_riscv64:
1084 case ZigLLVM_aarch64_be:
1085 case ZigLLVM_aarch64_32:
1086 case ZigLLVM_systemz:
1087 case ZigLLVM_mips64:
1088 case ZigLLVM_mips64el:
1089 case ZigLLVM_sparc:
1090 case ZigLLVM_sparcv9:
1091 case ZigLLVM_sparcel:
1092 case ZigLLVM_ppc:
1093 case ZigLLVM_ppcle:
1094 case ZigLLVM_ppc64:
1095 case ZigLLVM_ppc64le:
1096 return true;
1097
1098 default:
1099 return false;
1100 }
1101}
1102
1103bool target_has_f80(const ZigTarget *target) {
1104 switch (target->arch) {
1105 case ZigLLVM_x86:
1106 case ZigLLVM_x86_64:
1107 return true;
1108
1109 default:
1110 return false;
1111 }
1112}
1113
1114bool target_is_riscv(const ZigTarget *target) {
1115 return target->arch == ZigLLVM_riscv32 || target->arch == ZigLLVM_riscv64;
1116}
1117
1118bool target_is_sparc(const ZigTarget *target) {
1119 return target->arch == ZigLLVM_sparc || target->arch == ZigLLVM_sparcv9;
1120}
1121
1122bool target_is_mips(const ZigTarget *target) {
1123 return target->arch == ZigLLVM_mips || target->arch == ZigLLVM_mipsel ||
1124 target->arch == ZigLLVM_mips64 || target->arch == ZigLLVM_mips64el;
1125}
1126
1127bool target_is_ppc(const ZigTarget *target) {
1128 return target->arch == ZigLLVM_ppc || target->arch == ZigLLVM_ppcle ||
1129 target->arch == ZigLLVM_ppc64 || target->arch == ZigLLVM_ppc64le;
1130}
1131
1132// Returns the minimum alignment for every function pointer on the given
1133// architecture.
1134unsigned target_fn_ptr_align(const ZigTarget *target) {
1135 // TODO This is a pessimization but is always correct.
1136 return 1;
1137}
1138
1139// Returns the minimum alignment for every function on the given architecture.
1140unsigned target_fn_align(const ZigTarget *target) {
1141 switch (target->arch) {
1142 case ZigLLVM_riscv32:
1143 case ZigLLVM_riscv64:
1144 // TODO If the C extension is not present the value is 4.
1145 return 2;
1146 case ZigLLVM_ppc:
1147 case ZigLLVM_ppcle:
1148 case ZigLLVM_ppc64:
1149 case ZigLLVM_ppc64le:
1150 case ZigLLVM_aarch64:
1151 case ZigLLVM_aarch64_be:
1152 case ZigLLVM_aarch64_32:
1153 case ZigLLVM_sparc:
1154 case ZigLLVM_sparcel:
1155 case ZigLLVM_sparcv9:
1156 case ZigLLVM_mips:
1157 case ZigLLVM_mipsel:
1158 case ZigLLVM_mips64:
1159 case ZigLLVM_mips64el:
1160 return 4;
1161
1162 default:
1163 return 1;
1164 }
1165}
src/stage1/target.hpp deleted-92
...@@ -1,92 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_TARGET_HPP
9#define ZIG_TARGET_HPP
10
11#include "stage2.h"
12
13struct Buf;
14
15enum CIntType {
16 CIntTypeShort,
17 CIntTypeUShort,
18 CIntTypeInt,
19 CIntTypeUInt,
20 CIntTypeLong,
21 CIntTypeULong,
22 CIntTypeLongLong,
23 CIntTypeULongLong,
24
25 CIntTypeCount,
26};
27
28Error target_parse_arch(ZigLLVM_ArchType *arch, const char *arch_ptr, size_t arch_len);
29Error target_parse_os(Os *os, const char *os_ptr, size_t os_len);
30Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len);
31
32size_t target_arch_count(void);
33ZigLLVM_ArchType target_arch_enum(size_t index);
34const char *target_arch_name(ZigLLVM_ArchType arch);
35
36const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch);
37
38size_t target_vendor_count(void);
39ZigLLVM_VendorType target_vendor_enum(size_t index);
40
41size_t target_os_count(void);
42Os target_os_enum(size_t index);
43const char *target_os_name(Os os_type);
44
45size_t target_abi_count(void);
46ZigLLVM_EnvironmentType target_abi_enum(size_t index);
47const char *target_abi_name(ZigLLVM_EnvironmentType abi);
48ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os);
49
50
51size_t target_oformat_count(void);
52ZigLLVM_ObjectFormatType target_oformat_enum(size_t index);
53const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat);
54ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target);
55
56void target_triple_llvm(Buf *triple, const ZigTarget *target);
57void target_triple_zig(Buf *triple, const ZigTarget *target);
58
59void init_all_targets(void);
60
61void resolve_target_object_format(ZigTarget *target);
62
63uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id);
64
65const char *target_o_file_ext(const ZigTarget *target);
66const char *target_asm_file_ext(const ZigTarget *target);
67const char *target_llvm_ir_file_ext(const ZigTarget *target);
68
69ZigLLVM_OSType get_llvm_os_type(Os os_type);
70
71bool target_is_arm(const ZigTarget *target);
72bool target_is_mips(const ZigTarget *target);
73bool target_is_ppc(const ZigTarget *target);
74bool target_allows_addr_zero(const ZigTarget *target);
75bool target_has_valgrind_support(const ZigTarget *target);
76bool target_os_is_darwin(Os os);
77bool target_is_wasm(const ZigTarget *target);
78bool target_is_bpf(const ZigTarget *target);
79bool target_is_riscv(const ZigTarget *target);
80bool target_is_sparc(const ZigTarget *target);
81bool target_is_android(const ZigTarget *target);
82bool target_has_debug_info(const ZigTarget *target);
83bool target_long_double_is_f128(const ZigTarget *target);
84bool target_has_f80(const ZigTarget *target);
85
86uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);
87uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch);
88
89unsigned target_fn_ptr_align(const ZigTarget *target);
90unsigned target_fn_align(const ZigTarget *target);
91
92#endif
src/stage1/tokenizer.cpp deleted-1626
...@@ -1,1626 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "tokenizer.hpp"
9#include "util.hpp"
10
11#include <stdarg.h>
12#include <stdlib.h>
13#include <stdio.h>
14#include <inttypes.h>
15#include <limits.h>
16#include <errno.h>
17
18#define WHITESPACE \
19 ' ': \
20 case '\r': \
21 case '\n'
22
23#define DIGIT_NON_ZERO \
24 '1': \
25 case '2': \
26 case '3': \
27 case '4': \
28 case '5': \
29 case '6': \
30 case '7': \
31 case '8': \
32 case '9'
33
34#define DIGIT \
35 '0': \
36 case DIGIT_NON_ZERO
37
38#define HEXDIGIT \
39 'a': \
40 case 'b': \
41 case 'c': \
42 case 'd': \
43 case 'e': \
44 case 'f': \
45 case 'A': \
46 case 'B': \
47 case 'C': \
48 case 'D': \
49 case 'E': \
50 case 'F': \
51 case DIGIT
52
53#define ALPHA_EXCEPT_HEX_P_O_X \
54 'g': \
55 case 'h': \
56 case 'i': \
57 case 'j': \
58 case 'k': \
59 case 'l': \
60 case 'm': \
61 case 'n': \
62 case 'q': \
63 case 'r': \
64 case 's': \
65 case 't': \
66 case 'u': \
67 case 'v': \
68 case 'w': \
69 case 'y': \
70 case 'z': \
71 case 'G': \
72 case 'H': \
73 case 'I': \
74 case 'J': \
75 case 'K': \
76 case 'L': \
77 case 'M': \
78 case 'N': \
79 case 'O': \
80 case 'Q': \
81 case 'R': \
82 case 'S': \
83 case 'T': \
84 case 'U': \
85 case 'V': \
86 case 'W': \
87 case 'X': \
88 case 'Y': \
89 case 'Z'
90
91#define ALPHA_EXCEPT_E_B_O_X \
92 ALPHA_EXCEPT_HEX_P_O_X: \
93 case 'a': \
94 case 'c': \
95 case 'd': \
96 case 'f': \
97 case 'A': \
98 case 'B': \
99 case 'C': \
100 case 'D': \
101 case 'F': \
102 case 'p': \
103 case 'P'
104
105#define ALPHA_EXCEPT_HEX_AND_P \
106 ALPHA_EXCEPT_HEX_P_O_X: \
107 case 'o': \
108 case 'x'
109
110#define ALPHA_EXCEPT_E \
111 ALPHA_EXCEPT_HEX_AND_P: \
112 case 'a': \
113 case 'b': \
114 case 'c': \
115 case 'd': \
116 case 'f': \
117 case 'A': \
118 case 'B': \
119 case 'C': \
120 case 'D': \
121 case 'F': \
122 case 'p': \
123 case 'P'
124
125#define ALPHA \
126 ALPHA_EXCEPT_E: \
127 case 'e': \
128 case 'E'
129
130#define IDENTIFIER_CHAR \
131 ALPHA: \
132 case DIGIT: \
133 case '_'
134
135#define SYMBOL_START \
136 ALPHA: \
137 case '_'
138
139struct ZigKeyword {
140 const char *text;
141 TokenId token_id;
142};
143
144static const struct ZigKeyword zig_keywords[] = {
145 {"align", TokenIdKeywordAlign},
146 {"allowzero", TokenIdKeywordAllowZero},
147 {"and", TokenIdKeywordAnd},
148 {"anyframe", TokenIdKeywordAnyFrame},
149 {"anytype", TokenIdKeywordAnyType},
150 {"asm", TokenIdKeywordAsm},
151 {"async", TokenIdKeywordAsync},
152 {"await", TokenIdKeywordAwait},
153 {"break", TokenIdKeywordBreak},
154 {"callconv", TokenIdKeywordCallconv},
155 {"catch", TokenIdKeywordCatch},
156 {"comptime", TokenIdKeywordCompTime},
157 {"const", TokenIdKeywordConst},
158 {"continue", TokenIdKeywordContinue},
159 {"defer", TokenIdKeywordDefer},
160 {"else", TokenIdKeywordElse},
161 {"enum", TokenIdKeywordEnum},
162 {"errdefer", TokenIdKeywordErrdefer},
163 {"error", TokenIdKeywordError},
164 {"export", TokenIdKeywordExport},
165 {"extern", TokenIdKeywordExtern},
166 {"fn", TokenIdKeywordFn},
167 {"for", TokenIdKeywordFor},
168 {"if", TokenIdKeywordIf},
169 {"inline", TokenIdKeywordInline},
170 {"noalias", TokenIdKeywordNoAlias},
171 {"noinline", TokenIdKeywordNoInline},
172 {"nosuspend", TokenIdKeywordNoSuspend},
173 {"opaque", TokenIdKeywordOpaque},
174 {"or", TokenIdKeywordOr},
175 {"orelse", TokenIdKeywordOrElse},
176 {"packed", TokenIdKeywordPacked},
177 {"pub", TokenIdKeywordPub},
178 {"resume", TokenIdKeywordResume},
179 {"return", TokenIdKeywordReturn},
180 {"linksection", TokenIdKeywordLinkSection},
181 {"struct", TokenIdKeywordStruct},
182 {"suspend", TokenIdKeywordSuspend},
183 {"switch", TokenIdKeywordSwitch},
184 {"test", TokenIdKeywordTest},
185 {"threadlocal", TokenIdKeywordThreadLocal},
186 {"try", TokenIdKeywordTry},
187 {"union", TokenIdKeywordUnion},
188 {"unreachable", TokenIdKeywordUnreachable},
189 {"usingnamespace", TokenIdKeywordUsingNamespace},
190 {"var", TokenIdKeywordVar},
191 {"volatile", TokenIdKeywordVolatile},
192 {"while", TokenIdKeywordWhile},
193};
194
195// Returns TokenIdIdentifier if it is not a keyword.
196static TokenId zig_keyword_token(const char *name_ptr, size_t name_len) {
197 for (size_t i = 0; i < array_length(zig_keywords); i += 1) {
198 if (mem_eql_str(name_ptr, name_len, zig_keywords[i].text)) {
199 return zig_keywords[i].token_id;
200 }
201 }
202 return TokenIdIdentifier;
203}
204
205enum TokenizeState {
206 TokenizeState_start,
207 TokenizeState_identifier,
208 TokenizeState_builtin,
209 TokenizeState_string_literal,
210 TokenizeState_string_literal_backslash,
211 TokenizeState_multiline_string_literal_line,
212 TokenizeState_char_literal,
213 TokenizeState_char_literal_backslash,
214 TokenizeState_char_literal_hex_escape,
215 TokenizeState_char_literal_unicode_escape_saw_u,
216 TokenizeState_char_literal_unicode_escape,
217 TokenizeState_char_literal_unicode,
218 TokenizeState_char_literal_end,
219 TokenizeState_backslash,
220 TokenizeState_equal,
221 TokenizeState_bang,
222 TokenizeState_pipe,
223 TokenizeState_minus,
224 TokenizeState_minus_percent,
225 TokenizeState_minus_pipe,
226 TokenizeState_asterisk,
227 TokenizeState_asterisk_percent,
228 TokenizeState_asterisk_pipe,
229 TokenizeState_slash,
230 TokenizeState_line_comment_start,
231 TokenizeState_line_comment,
232 TokenizeState_doc_comment_start,
233 TokenizeState_doc_comment,
234 TokenizeState_container_doc_comment,
235 TokenizeState_zero,
236 TokenizeState_int_literal_dec,
237 TokenizeState_int_literal_dec_no_underscore,
238 TokenizeState_int_literal_bin,
239 TokenizeState_int_literal_bin_no_underscore,
240 TokenizeState_int_literal_oct,
241 TokenizeState_int_literal_oct_no_underscore,
242 TokenizeState_int_literal_hex,
243 TokenizeState_int_literal_hex_no_underscore,
244 TokenizeState_num_dot_dec,
245 TokenizeState_num_dot_hex,
246 TokenizeState_float_fraction_dec,
247 TokenizeState_float_fraction_dec_no_underscore,
248 TokenizeState_float_fraction_hex,
249 TokenizeState_float_fraction_hex_no_underscore,
250 TokenizeState_float_exponent_unsigned,
251 TokenizeState_float_exponent_num,
252 TokenizeState_float_exponent_num_no_underscore,
253 TokenizeState_ampersand,
254 TokenizeState_caret,
255 TokenizeState_percent,
256 TokenizeState_plus,
257 TokenizeState_plus_percent,
258 TokenizeState_plus_pipe,
259 TokenizeState_angle_bracket_left,
260 TokenizeState_angle_bracket_angle_bracket_left,
261 TokenizeState_angle_bracket_angle_bracket_left_pipe,
262 TokenizeState_angle_bracket_right,
263 TokenizeState_angle_bracket_angle_bracket_right,
264 TokenizeState_period,
265 TokenizeState_period_2,
266 TokenizeState_period_asterisk,
267 TokenizeState_saw_at_sign,
268 TokenizeState_error,
269};
270
271
272struct Tokenize {
273 Tokenization *out;
274 size_t pos;
275 TokenizeState state;
276 uint32_t line;
277 uint32_t column;
278};
279
280ATTRIBUTE_PRINTF(2, 3)
281static void tokenize_error(Tokenize *t, const char *format, ...) {
282 t->state = TokenizeState_error;
283
284 t->out->err_byte_offset = t->pos;
285
286 va_list ap;
287 va_start(ap, format);
288 t->out->err = buf_vprintf(format, ap);
289 va_end(ap);
290}
291
292static void begin_token(Tokenize *t, TokenId id) {
293 t->out->ids.append(id);
294 TokenLoc tok_loc;
295 tok_loc.offset = (uint32_t) t->pos;
296 tok_loc.line = t->line;
297 tok_loc.column = t->column;
298 t->out->locs.append(tok_loc);
299}
300
301static void cancel_token(Tokenize *t) {
302 t->out->ids.pop();
303 t->out->locs.pop();
304}
305
306static const char* get_escape_shorthand(uint8_t c) {
307 switch (c) {
308 case '\0':
309 return "\\0";
310 case '\a':
311 return "\\a";
312 case '\b':
313 return "\\b";
314 case '\t':
315 return "\\t";
316 case '\n':
317 return "\\n";
318 case '\v':
319 return "\\v";
320 case '\f':
321 return "\\f";
322 case '\r':
323 return "\\r";
324 default:
325 return nullptr;
326 }
327}
328
329static void invalid_eof(Tokenize *t) {
330 return tokenize_error(t, "unexpected End-Of-File");
331}
332
333static void invalid_char_error(Tokenize *t, uint8_t c) {
334 if (c == 0) {
335 return invalid_eof(t);
336 }
337
338 if (c == '\r') {
339 tokenize_error(t, "invalid carriage return, only '\\n' line endings are supported");
340 return;
341 }
342
343 const char *sh = get_escape_shorthand(c);
344 if (sh) {
345 tokenize_error(t, "invalid character: '%s'", sh);
346 return;
347 }
348
349 if (isprint(c)) {
350 tokenize_error(t, "invalid character: '%c'", c);
351 return;
352 }
353
354 tokenize_error(t, "invalid character: '\\x%02x'", c);
355}
356
357void tokenize(const char *source, Tokenization *out) {
358 Tokenize t = {0};
359 t.out = out;
360
361 size_t remaining_code_units;
362 size_t seen_escape_digits;
363
364 // Skip the UTF-8 BOM if present.
365 if (source[0] == (char)0xef &&
366 source[1] == (char)0xbb &&
367 source[2] == (char)0xbf)
368 {
369 t.pos += 3;
370 }
371
372 // Invalid token takes up index 0 so that index 0 can mean "none".
373 begin_token(&t, TokenIdCount);
374
375 for (;;) {
376 uint8_t c = source[t.pos];
377 switch (t.state) {
378 case TokenizeState_error:
379 goto eof;
380 case TokenizeState_start:
381 switch (c) {
382 case 0:
383 goto eof;
384 case WHITESPACE:
385 break;
386 case '"':
387 begin_token(&t, TokenIdStringLiteral);
388 t.state = TokenizeState_string_literal;
389 break;
390 case '\'':
391 begin_token(&t, TokenIdCharLiteral);
392 t.state = TokenizeState_char_literal;
393 break;
394 case ALPHA:
395 case '_':
396 t.state = TokenizeState_identifier;
397 begin_token(&t, TokenIdIdentifier);
398 break;
399 case '@':
400 begin_token(&t, TokenIdBuiltin);
401 t.state = TokenizeState_saw_at_sign;
402 break;
403 case '=':
404 begin_token(&t, TokenIdEq);
405 t.state = TokenizeState_equal;
406 break;
407 case '!':
408 begin_token(&t, TokenIdBang);
409 t.state = TokenizeState_bang;
410 break;
411 case '|':
412 begin_token(&t, TokenIdBinOr);
413 t.state = TokenizeState_pipe;
414 break;
415 case '(':
416 begin_token(&t, TokenIdLParen);
417 break;
418 case ')':
419 begin_token(&t, TokenIdRParen);
420 break;
421 case '[':
422 begin_token(&t, TokenIdLBracket);
423 break;
424 case ']':
425 begin_token(&t, TokenIdRBracket);
426 break;
427 case ';':
428 begin_token(&t, TokenIdSemicolon);
429 break;
430 case ',':
431 begin_token(&t, TokenIdComma);
432 break;
433 case '?':
434 begin_token(&t, TokenIdQuestion);
435 break;
436 case ':':
437 begin_token(&t, TokenIdColon);
438 break;
439 case '%':
440 begin_token(&t, TokenIdPercent);
441 t.state = TokenizeState_percent;
442 break;
443 case '*':
444 begin_token(&t, TokenIdStar);
445 t.state = TokenizeState_asterisk;
446 break;
447 case '+':
448 begin_token(&t, TokenIdPlus);
449 t.state = TokenizeState_plus;
450 break;
451 case '<':
452 begin_token(&t, TokenIdCmpLessThan);
453 t.state = TokenizeState_angle_bracket_left;
454 break;
455 case '>':
456 begin_token(&t, TokenIdCmpGreaterThan);
457 t.state = TokenizeState_angle_bracket_right;
458 break;
459 case '^':
460 begin_token(&t, TokenIdBinXor);
461 t.state = TokenizeState_caret;
462 break;
463 case '\\':
464 begin_token(&t, TokenIdMultilineStringLiteralLine);
465 t.state = TokenizeState_backslash;
466 break;
467 case '{':
468 begin_token(&t, TokenIdLBrace);
469 break;
470 case '}':
471 begin_token(&t, TokenIdRBrace);
472 break;
473 case '~':
474 begin_token(&t, TokenIdTilde);
475 break;
476 case '.':
477 begin_token(&t, TokenIdDot);
478 t.state = TokenizeState_period;
479 break;
480 case '-':
481 begin_token(&t, TokenIdDash);
482 t.state = TokenizeState_minus;
483 break;
484 case '/':
485 begin_token(&t, TokenIdSlash);
486 t.state = TokenizeState_slash;
487 break;
488 case '&':
489 begin_token(&t, TokenIdAmpersand);
490 t.state = TokenizeState_ampersand;
491 break;
492 case '0':
493 t.state = TokenizeState_zero;
494 begin_token(&t, TokenIdIntLiteral);
495 break;
496 case DIGIT_NON_ZERO:
497 t.state = TokenizeState_int_literal_dec;
498 begin_token(&t, TokenIdIntLiteral);
499 break;
500 default:
501 invalid_char_error(&t, c);
502 }
503 break;
504 case TokenizeState_saw_at_sign:
505 switch (c) {
506 case 0:
507 invalid_eof(&t);
508 goto eof;
509 case '"':
510 t.out->ids.last() = TokenIdIdentifier;
511 t.state = TokenizeState_string_literal;
512 break;
513 case IDENTIFIER_CHAR:
514 t.state = TokenizeState_builtin;
515 break;
516 default:
517 invalid_char_error(&t, c);
518 }
519 break;
520 case TokenizeState_ampersand:
521 switch (c) {
522 case 0:
523 goto eof;
524 case '&':
525 tokenize_error(&t, "`&&` is invalid. Note that `and` is boolean AND");
526 break;
527 case '=':
528 t.out->ids.last() = TokenIdBitAndEq;
529 t.state = TokenizeState_start;
530 break;
531 default:
532 t.state = TokenizeState_start;
533 continue;
534 }
535 break;
536 case TokenizeState_asterisk:
537 switch (c) {
538 case 0:
539 goto eof;
540 case '=':
541 t.out->ids.last() = TokenIdTimesEq;
542 t.state = TokenizeState_start;
543 break;
544 case '*':
545 t.out->ids.last() = TokenIdStarStar;
546 t.state = TokenizeState_start;
547 break;
548 case '%':
549 t.state = TokenizeState_asterisk_percent;
550 break;
551 case '|':
552 t.state = TokenizeState_asterisk_pipe;
553 break;
554 default:
555 t.state = TokenizeState_start;
556 continue;
557 }
558 break;
559 case TokenizeState_asterisk_percent:
560 switch (c) {
561 case 0:
562 t.out->ids.last() = TokenIdTimesPercent;
563 goto eof;
564 case '=':
565 t.out->ids.last() = TokenIdTimesPercentEq;
566 t.state = TokenizeState_start;
567 break;
568 default:
569 t.out->ids.last() = TokenIdTimesPercent;
570 t.state = TokenizeState_start;
571 continue;
572 }
573 break;
574 case TokenizeState_asterisk_pipe:
575 switch (c) {
576 case 0:
577 t.out->ids.last() = TokenIdTimesPipe;
578 goto eof;
579 case '=':
580 t.out->ids.last() = TokenIdTimesPipeEq;
581 t.state = TokenizeState_start;
582 break;
583 default:
584 t.out->ids.last() = TokenIdTimesPipe;
585 t.state = TokenizeState_start;
586 continue;
587 }
588 break;
589 case TokenizeState_percent:
590 switch (c) {
591 case 0:
592 goto eof;
593 case '=':
594 t.out->ids.last() = TokenIdModEq;
595 t.state = TokenizeState_start;
596 break;
597 default:
598 t.state = TokenizeState_start;
599 continue;
600 }
601 break;
602 case TokenizeState_plus:
603 switch (c) {
604 case 0:
605 goto eof;
606 case '=':
607 t.out->ids.last() = TokenIdPlusEq;
608 t.state = TokenizeState_start;
609 break;
610 case '+':
611 t.out->ids.last() = TokenIdPlusPlus;
612 t.state = TokenizeState_start;
613 break;
614 case '%':
615 t.state = TokenizeState_plus_percent;
616 break;
617 case '|':
618 t.state = TokenizeState_plus_pipe;
619 break;
620 default:
621 t.state = TokenizeState_start;
622 continue;
623 }
624 break;
625 case TokenizeState_plus_percent:
626 switch (c) {
627 case 0:
628 t.out->ids.last() = TokenIdPlusPercent;
629 goto eof;
630 case '=':
631 t.out->ids.last() = TokenIdPlusPercentEq;
632 t.state = TokenizeState_start;
633 break;
634 default:
635 t.out->ids.last() = TokenIdPlusPercent;
636 t.state = TokenizeState_start;
637 continue;
638 }
639 break;
640 case TokenizeState_plus_pipe:
641 switch (c) {
642 case 0:
643 t.out->ids.last() = TokenIdPlusPipe;
644 goto eof;
645 case '=':
646 t.out->ids.last() = TokenIdPlusPipeEq;
647 t.state = TokenizeState_start;
648 break;
649 default:
650 t.out->ids.last() = TokenIdPlusPipe;
651 t.state = TokenizeState_start;
652 continue;
653 }
654 break;
655 case TokenizeState_caret:
656 switch (c) {
657 case 0:
658 goto eof;
659 case '=':
660 t.out->ids.last() = TokenIdBitXorEq;
661 t.state = TokenizeState_start;
662 break;
663 default:
664 t.state = TokenizeState_start;
665 continue;
666 }
667 break;
668 case TokenizeState_identifier:
669 switch (c) {
670 case 0: {
671 uint32_t start_pos = t.out->locs.last().offset;
672 t.out->ids.last() = zig_keyword_token(
673 source + start_pos, t.pos - start_pos);
674 goto eof;
675 }
676 case IDENTIFIER_CHAR:
677 break;
678 default: {
679 uint32_t start_pos = t.out->locs.last().offset;
680 t.out->ids.last() = zig_keyword_token(
681 source + start_pos, t.pos - start_pos);
682
683 t.state = TokenizeState_start;
684 continue;
685 }
686 }
687 break;
688 case TokenizeState_builtin:
689 switch (c) {
690 case 0:
691 goto eof;
692 case IDENTIFIER_CHAR:
693 break;
694 default:
695 t.state = TokenizeState_start;
696 continue;
697 }
698 break;
699 case TokenizeState_backslash:
700 switch (c) {
701 case '\\':
702 t.state = TokenizeState_multiline_string_literal_line;
703 break;
704 default:
705 invalid_char_error(&t, c);
706 break;
707 }
708 break;
709 case TokenizeState_string_literal:
710 switch (c) {
711 case 0:
712 invalid_eof(&t);
713 goto eof;
714 case '\\':
715 t.state = TokenizeState_string_literal_backslash;
716 break;
717 case '"':
718 t.state = TokenizeState_start;
719 break;
720 case '\n':
721 case '\r':
722 tokenize_error(&t, "newline not allowed in string literal");
723 break;
724 default:
725 break;
726 }
727 break;
728 case TokenizeState_string_literal_backslash:
729 switch (c) {
730 case 0:
731 invalid_eof(&t);
732 goto eof;
733 case '\n':
734 case '\r':
735 tokenize_error(&t, "newline not allowed in string literal");
736 break;
737 default:
738 t.state = TokenizeState_string_literal;
739 break;
740 }
741 break;
742 case TokenizeState_char_literal:
743 if (c == 0) {
744 invalid_eof(&t);
745 goto eof;
746 } else if (c == '\\') {
747 t.state = TokenizeState_char_literal_backslash;
748 } else if (c == '\'') {
749 tokenize_error(&t, "expected character");
750 } else if ((c >= 0x80 && c <= 0xbf) || c >= 0xf8) {
751 // 10xxxxxx
752 // 11111xxx
753 invalid_char_error(&t, c);
754 } else if (c >= 0xc0 && c <= 0xdf) {
755 // 110xxxxx
756 remaining_code_units = 1;
757 t.state = TokenizeState_char_literal_unicode;
758 } else if (c >= 0xe0 && c <= 0xef) {
759 // 1110xxxx
760 remaining_code_units = 2;
761 t.state = TokenizeState_char_literal_unicode;
762 } else if (c >= 0xf0 && c <= 0xf7) {
763 // 11110xxx
764 remaining_code_units = 3;
765 t.state = TokenizeState_char_literal_unicode;
766 } else {
767 t.state = TokenizeState_char_literal_end;
768 }
769 break;
770 case TokenizeState_char_literal_backslash:
771 switch (c) {
772 case 0:
773 invalid_eof(&t);
774 goto eof;
775 case '\n':
776 case '\r':
777 tokenize_error(&t, "newline not allowed in character literal");
778 break;
779 case 'x':
780 t.state = TokenizeState_char_literal_hex_escape;
781 seen_escape_digits = 0;
782 break;
783 case 'u':
784 t.state = TokenizeState_char_literal_unicode_escape_saw_u;
785 break;
786 case 'U':
787 invalid_char_error(&t, c);
788 break;
789 default:
790 t.state = TokenizeState_char_literal_end;
791 break;
792 }
793 break;
794 case TokenizeState_char_literal_hex_escape:
795 switch (c) {
796 case ALPHA:
797 case DIGIT:
798 seen_escape_digits += 1;
799 if (seen_escape_digits == 2) {
800 t.state = TokenizeState_char_literal_end;
801 }
802 break;
803 default:
804 tokenize_error(&t, "expected hex digit");
805 break;
806 }
807 break;
808 case TokenizeState_char_literal_unicode_escape_saw_u:
809 switch (c) {
810 case '{':
811 t.state = TokenizeState_char_literal_unicode_escape;
812 seen_escape_digits = 0;
813 break;
814 default:
815 tokenize_error(&t, "expected '{' to begin unicode escape sequence");
816 break;
817 }
818 break;
819 case TokenizeState_char_literal_unicode_escape:
820 switch (c) {
821 case ALPHA:
822 case DIGIT:
823 seen_escape_digits += 1;
824 break;
825 case '}':
826 if (seen_escape_digits == 0) {
827 tokenize_error(&t, "empty unicode escape sequence");
828 break;
829 }
830 t.state = TokenizeState_char_literal_end;
831 break;
832 default:
833 tokenize_error(&t, "expected hex digit");
834 break;
835 }
836 break;
837 case TokenizeState_char_literal_end:
838 switch (c) {
839 case '\'':
840 t.state = TokenizeState_start;
841 break;
842 default:
843 invalid_char_error(&t, c);
844 break;
845 }
846 break;
847 case TokenizeState_char_literal_unicode:
848 if (c >= 0x80 && c <= 0xbf) {
849 remaining_code_units -= 1;
850 if (remaining_code_units == 0) {
851 t.state = TokenizeState_char_literal_end;
852 }
853 } else {
854 invalid_char_error(&t, c);
855 }
856 break;
857 case TokenizeState_multiline_string_literal_line:
858 switch (c) {
859 case 0:
860 goto eof;
861 case '\n':
862 t.state = TokenizeState_start;
863 break;
864 default:
865 break;
866 }
867 break;
868 case TokenizeState_bang:
869 switch (c) {
870 case 0:
871 goto eof;
872 case '=':
873 t.out->ids.last() = TokenIdCmpNotEq;
874 t.state = TokenizeState_start;
875 break;
876 default:
877 t.state = TokenizeState_start;
878 continue;
879 }
880 break;
881 case TokenizeState_pipe:
882 switch (c) {
883 case 0:
884 goto eof;
885 case '=':
886 t.out->ids.last() = TokenIdBitOrEq;
887 t.state = TokenizeState_start;
888 break;
889 case '|':
890 t.out->ids.last() = TokenIdBarBar;
891 t.state = TokenizeState_start;
892 break;
893 default:
894 t.state = TokenizeState_start;
895 continue;
896 }
897 break;
898 case TokenizeState_equal:
899 switch (c) {
900 case 0:
901 goto eof;
902 case '=':
903 t.out->ids.last() = TokenIdCmpEq;
904 t.state = TokenizeState_start;
905 break;
906 case '>':
907 t.out->ids.last() = TokenIdFatArrow;
908 t.state = TokenizeState_start;
909 break;
910 default:
911 t.state = TokenizeState_start;
912 continue;
913 }
914 break;
915 case TokenizeState_minus:
916 switch (c) {
917 case 0:
918 goto eof;
919 case '>':
920 t.out->ids.last() = TokenIdArrow;
921 t.state = TokenizeState_start;
922 break;
923 case '=':
924 t.out->ids.last() = TokenIdMinusEq;
925 t.state = TokenizeState_start;
926 break;
927 case '%':
928 t.state = TokenizeState_minus_percent;
929 break;
930 case '|':
931 t.state = TokenizeState_minus_pipe;
932 break;
933 default:
934 t.state = TokenizeState_start;
935 continue;
936 }
937 break;
938 case TokenizeState_minus_percent:
939 switch (c) {
940 case 0:
941 t.out->ids.last() = TokenIdMinusPercent;
942 goto eof;
943 case '=':
944 t.out->ids.last() = TokenIdMinusPercentEq;
945 t.state = TokenizeState_start;
946 break;
947 default:
948 t.out->ids.last() = TokenIdMinusPercent;
949 t.state = TokenizeState_start;
950 continue;
951 }
952 break;
953 case TokenizeState_minus_pipe:
954 switch (c) {
955 case 0:
956 t.out->ids.last() = TokenIdMinusPipe;
957 goto eof;
958 case '=':
959 t.out->ids.last() = TokenIdMinusPipeEq;
960 t.state = TokenizeState_start;
961 break;
962 default:
963 t.out->ids.last() = TokenIdMinusPipe;
964 t.state = TokenizeState_start;
965 continue;
966 }
967 break;
968 case TokenizeState_angle_bracket_left:
969 switch (c) {
970 case 0:
971 goto eof;
972 case '=':
973 t.out->ids.last() = TokenIdCmpLessOrEq;
974 t.state = TokenizeState_start;
975 break;
976 case '<':
977 t.state = TokenizeState_angle_bracket_angle_bracket_left;
978 break;
979 default:
980 t.state = TokenizeState_start;
981 continue;
982 }
983 break;
984 case TokenizeState_angle_bracket_angle_bracket_left:
985 switch (c) {
986 case 0:
987 t.out->ids.last() = TokenIdBitShiftLeft;
988 goto eof;
989 case '=':
990 t.out->ids.last() = TokenIdBitShiftLeftEq;
991 t.state = TokenizeState_start;
992 break;
993 case '|':
994 t.state = TokenizeState_angle_bracket_angle_bracket_left_pipe;
995 break;
996 default:
997 t.out->ids.last() = TokenIdBitShiftLeft;
998 t.state = TokenizeState_start;
999 continue;
1000 }
1001 break;
1002 case TokenizeState_angle_bracket_angle_bracket_left_pipe:
1003 switch (c) {
1004 case 0:
1005 t.out->ids.last() = TokenIdBitShiftLeftPipe;
1006 goto eof;
1007 case '=':
1008 t.out->ids.last() = TokenIdBitShiftLeftPipeEq;
1009 t.state = TokenizeState_start;
1010 break;
1011 default:
1012 t.out->ids.last() = TokenIdBitShiftLeftPipe;
1013 t.state = TokenizeState_start;
1014 continue;
1015 }
1016 break;
1017 case TokenizeState_angle_bracket_right:
1018 switch (c) {
1019 case 0:
1020 goto eof;
1021 case '=':
1022 t.out->ids.last() = TokenIdCmpGreaterOrEq;
1023 t.state = TokenizeState_start;
1024 break;
1025 case '>':
1026 t.state = TokenizeState_angle_bracket_angle_bracket_right;
1027 break;
1028 default:
1029 t.state = TokenizeState_start;
1030 continue;
1031 }
1032 break;
1033 case TokenizeState_angle_bracket_angle_bracket_right:
1034 switch (c) {
1035 case 0:
1036 t.out->ids.last() = TokenIdBitShiftRight;
1037 goto eof;
1038 case '=':
1039 t.out->ids.last() = TokenIdBitShiftRightEq;
1040 t.state = TokenizeState_start;
1041 break;
1042 default:
1043 t.out->ids.last() = TokenIdBitShiftRight;
1044 t.state = TokenizeState_start;
1045 continue;
1046 }
1047 break;
1048 case TokenizeState_period:
1049 switch (c) {
1050 case 0:
1051 goto eof;
1052 case '.':
1053 t.state = TokenizeState_period_2;
1054 break;
1055 case '*':
1056 t.state = TokenizeState_period_asterisk;
1057 break;
1058 default:
1059 t.state = TokenizeState_start;
1060 continue;
1061 }
1062 break;
1063 case TokenizeState_period_2:
1064 switch (c) {
1065 case 0:
1066 t.out->ids.last() = TokenIdEllipsis2;
1067 goto eof;
1068 case '.':
1069 t.out->ids.last() = TokenIdEllipsis3;
1070 t.state = TokenizeState_start;
1071 break;
1072 default:
1073 t.out->ids.last() = TokenIdEllipsis2;
1074 t.state = TokenizeState_start;
1075 continue;
1076 }
1077 break;
1078 case TokenizeState_period_asterisk:
1079 switch (c) {
1080 case 0:
1081 t.out->ids.last() = TokenIdDotStar;
1082 goto eof;
1083 case '*':
1084 tokenize_error(&t, "`.*` cannot be followed by `*`. Are you missing a space?");
1085 break;
1086 default:
1087 t.out->ids.last() = TokenIdDotStar;
1088 t.state = TokenizeState_start;
1089 continue;
1090 }
1091 break;
1092 case TokenizeState_slash:
1093 switch (c) {
1094 case 0:
1095 goto eof;
1096 case '/':
1097 t.state = TokenizeState_line_comment_start;
1098 break;
1099 case '=':
1100 t.out->ids.last() = TokenIdDivEq;
1101 t.state = TokenizeState_start;
1102 break;
1103 default:
1104 t.state = TokenizeState_start;
1105 continue;
1106 }
1107 break;
1108 case TokenizeState_line_comment_start:
1109 switch (c) {
1110 case 0:
1111 goto eof;
1112 case '/':
1113 t.state = TokenizeState_doc_comment_start;
1114 break;
1115 case '!':
1116 t.out->ids.last() = TokenIdContainerDocComment;
1117 t.state = TokenizeState_container_doc_comment;
1118 break;
1119 case '\n':
1120 cancel_token(&t);
1121 t.state = TokenizeState_start;
1122 break;
1123 default:
1124 cancel_token(&t);
1125 t.state = TokenizeState_line_comment;
1126 break;
1127 }
1128 break;
1129 case TokenizeState_doc_comment_start:
1130 switch (c) {
1131 case 0:
1132 t.out->ids.last() = TokenIdDocComment;
1133 goto eof;
1134 case '/':
1135 cancel_token(&t);
1136 t.state = TokenizeState_line_comment;
1137 break;
1138 case '\n':
1139 t.out->ids.last() = TokenIdDocComment;
1140 t.state = TokenizeState_start;
1141 break;
1142 default:
1143 t.out->ids.last() = TokenIdDocComment;
1144 t.state = TokenizeState_doc_comment;
1145 break;
1146 }
1147 break;
1148 case TokenizeState_line_comment:
1149 switch (c) {
1150 case 0:
1151 goto eof;
1152 case '\n':
1153 t.state = TokenizeState_start;
1154 break;
1155 default:
1156 break;
1157 }
1158 break;
1159 case TokenizeState_doc_comment:
1160 case TokenizeState_container_doc_comment:
1161 switch (c) {
1162 case 0:
1163 goto eof;
1164 case '\n':
1165 t.state = TokenizeState_start;
1166 break;
1167 default:
1168 // do nothing
1169 break;
1170 }
1171 break;
1172 case TokenizeState_zero:
1173 switch (c) {
1174 case 0:
1175 goto eof;
1176 case 'b':
1177 t.state = TokenizeState_int_literal_bin_no_underscore;
1178 break;
1179 case 'o':
1180 t.state = TokenizeState_int_literal_oct_no_underscore;
1181 break;
1182 case 'x':
1183 t.state = TokenizeState_int_literal_hex_no_underscore;
1184 break;
1185 case DIGIT:
1186 case '_':
1187 case '.':
1188 case 'e':
1189 case 'E':
1190 // Reinterpret as a decimal number.
1191 t.state = TokenizeState_int_literal_dec;
1192 continue;
1193 case ALPHA_EXCEPT_E_B_O_X:
1194 invalid_char_error(&t, c);
1195 break;
1196 default:
1197 t.state = TokenizeState_start;
1198 continue;
1199 }
1200 break;
1201 case TokenizeState_int_literal_bin_no_underscore:
1202 switch (c) {
1203 case '0':
1204 case '1':
1205 t.state = TokenizeState_int_literal_bin;
1206 break;
1207 default:
1208 invalid_char_error(&t, c);
1209 }
1210 break;
1211 case TokenizeState_int_literal_bin:
1212 switch (c) {
1213 case 0:
1214 goto eof;
1215 case '_':
1216 t.state = TokenizeState_int_literal_bin_no_underscore;
1217 break;
1218 case '0':
1219 case '1':
1220 break;
1221 case '2':
1222 case '3':
1223 case '4':
1224 case '5':
1225 case '6':
1226 case '7':
1227 case '8':
1228 case '9':
1229 case ALPHA:
1230 invalid_char_error(&t, c);
1231 break;
1232 default:
1233 t.state = TokenizeState_start;
1234 continue;
1235 }
1236 break;
1237 case TokenizeState_int_literal_oct_no_underscore:
1238 switch (c) {
1239 case '0':
1240 case '1':
1241 case '2':
1242 case '3':
1243 case '4':
1244 case '5':
1245 case '6':
1246 case '7':
1247 t.state = TokenizeState_int_literal_oct;
1248 break;
1249 default:
1250 invalid_char_error(&t, c);
1251 break;
1252 }
1253 break;
1254 case TokenizeState_int_literal_oct:
1255 switch (c) {
1256 case 0:
1257 goto eof;
1258 case '_':
1259 t.state = TokenizeState_int_literal_oct_no_underscore;
1260 break;
1261 case '0':
1262 case '1':
1263 case '2':
1264 case '3':
1265 case '4':
1266 case '5':
1267 case '6':
1268 case '7':
1269 break;
1270 case ALPHA:
1271 case '8':
1272 case '9':
1273 invalid_char_error(&t, c);
1274 break;
1275 default:
1276 t.state = TokenizeState_start;
1277 continue;
1278 }
1279 break;
1280 case TokenizeState_int_literal_dec_no_underscore:
1281 switch (c) {
1282 case DIGIT:
1283 t.state = TokenizeState_int_literal_dec;
1284 break;
1285 default:
1286 invalid_char_error(&t, c);
1287 break;
1288 }
1289 break;
1290 case TokenizeState_int_literal_dec:
1291 switch (c) {
1292 case 0:
1293 goto eof;
1294 case '_':
1295 t.state = TokenizeState_int_literal_dec_no_underscore;
1296 break;
1297 case '.':
1298 t.state = TokenizeState_num_dot_dec;
1299 t.out->ids.last() = TokenIdFloatLiteral;
1300 break;
1301 case 'e':
1302 case 'E':
1303 t.state = TokenizeState_float_exponent_unsigned;
1304 t.out->ids.last() = TokenIdFloatLiteral;
1305 break;
1306 case DIGIT:
1307 break;
1308 case ALPHA_EXCEPT_E:
1309 invalid_char_error(&t, c);
1310 break;
1311 default:
1312 t.state = TokenizeState_start;
1313 continue;
1314 }
1315 break;
1316 case TokenizeState_int_literal_hex_no_underscore:
1317 switch (c) {
1318 case HEXDIGIT:
1319 t.state = TokenizeState_int_literal_hex;
1320 break;
1321 default:
1322 invalid_char_error(&t, c);
1323 }
1324 break;
1325 case TokenizeState_int_literal_hex:
1326 switch (c) {
1327 case 0:
1328 goto eof;
1329 case '_':
1330 t.state = TokenizeState_int_literal_hex_no_underscore;
1331 break;
1332 case '.':
1333 t.state = TokenizeState_num_dot_hex;
1334 t.out->ids.last() = TokenIdFloatLiteral;
1335 break;
1336 case 'p':
1337 case 'P':
1338 t.state = TokenizeState_float_exponent_unsigned;
1339 t.out->ids.last() = TokenIdFloatLiteral;
1340 break;
1341 case HEXDIGIT:
1342 break;
1343 case ALPHA_EXCEPT_HEX_AND_P:
1344 invalid_char_error(&t, c);
1345 break;
1346 default:
1347 t.state = TokenizeState_start;
1348 continue;
1349 }
1350 break;
1351 case TokenizeState_num_dot_dec:
1352 switch (c) {
1353 case 0:
1354 goto eof;
1355 case '.':
1356 t.out->ids.last() = TokenIdIntLiteral;
1357 t.pos -= 1;
1358 t.column -= 1;
1359 t.state = TokenizeState_start;
1360 continue;
1361 case DIGIT:
1362 t.state = TokenizeState_float_fraction_dec;
1363 break;
1364 default:
1365 invalid_char_error(&t, c);
1366 break;
1367 }
1368 break;
1369 case TokenizeState_num_dot_hex:
1370 switch (c) {
1371 case 0:
1372 goto eof;
1373 case '.':
1374 t.out->ids.last() = TokenIdIntLiteral;
1375 t.pos -= 1;
1376 t.column -= 1;
1377 t.state = TokenizeState_start;
1378 continue;
1379 case HEXDIGIT:
1380 t.out->ids.last() = TokenIdFloatLiteral;
1381 t.state = TokenizeState_float_fraction_hex;
1382 break;
1383 default:
1384 invalid_char_error(&t, c);
1385 break;
1386 }
1387 break;
1388 case TokenizeState_float_fraction_dec_no_underscore:
1389 switch (c) {
1390 case DIGIT:
1391 t.state = TokenizeState_float_fraction_dec;
1392 break;
1393 default:
1394 invalid_char_error(&t, c);
1395 }
1396 break;
1397 case TokenizeState_float_fraction_dec:
1398 switch (c) {
1399 case 0:
1400 goto eof;
1401 case '_':
1402 t.state = TokenizeState_float_fraction_dec_no_underscore;
1403 break;
1404 case 'e':
1405 case 'E':
1406 t.state = TokenizeState_float_exponent_unsigned;
1407 break;
1408 case DIGIT:
1409 break;
1410 case ALPHA_EXCEPT_E:
1411 invalid_char_error(&t, c);
1412 break;
1413 default:
1414 t.state = TokenizeState_start;
1415 continue;
1416 }
1417 break;
1418 case TokenizeState_float_fraction_hex_no_underscore:
1419 switch (c) {
1420 case HEXDIGIT:
1421 t.state = TokenizeState_float_fraction_hex;
1422 break;
1423 default:
1424 invalid_char_error(&t, c);
1425 }
1426 break;
1427 case TokenizeState_float_fraction_hex:
1428 switch (c) {
1429 case 0:
1430 goto eof;
1431 case '_':
1432 t.state = TokenizeState_float_fraction_hex_no_underscore;
1433 break;
1434 case 'p':
1435 case 'P':
1436 t.state = TokenizeState_float_exponent_unsigned;
1437 break;
1438 case HEXDIGIT:
1439 break;
1440 case ALPHA_EXCEPT_HEX_AND_P:
1441 invalid_char_error(&t, c);
1442 break;
1443 default:
1444 t.state = TokenizeState_start;
1445 continue;
1446 }
1447 break;
1448 case TokenizeState_float_exponent_unsigned:
1449 switch (c) {
1450 case '+':
1451 case '-':
1452 t.state = TokenizeState_float_exponent_num_no_underscore;
1453 break;
1454 default:
1455 // Reinterpret as a normal exponent number.
1456 t.state = TokenizeState_float_exponent_num_no_underscore;
1457 continue;
1458 }
1459 break;
1460 case TokenizeState_float_exponent_num_no_underscore:
1461 switch (c) {
1462 case DIGIT:
1463 t.state = TokenizeState_float_exponent_num;
1464 break;
1465 default:
1466 invalid_char_error(&t, c);
1467 }
1468 break;
1469 case TokenizeState_float_exponent_num:
1470 switch (c) {
1471 case 0:
1472 goto eof;
1473 case '_':
1474 t.state = TokenizeState_float_exponent_num_no_underscore;
1475 break;
1476 case DIGIT:
1477 break;
1478 case ALPHA:
1479 invalid_char_error(&t, c);
1480 break;
1481 default:
1482 t.state = TokenizeState_start;
1483 continue;
1484 }
1485 break;
1486 }
1487 t.pos += 1;
1488 if (c == '\n') {
1489 t.line += 1;
1490 t.column = 0;
1491 } else {
1492 t.column += 1;
1493 }
1494 }
1495eof:;
1496
1497 begin_token(&t, TokenIdEof);
1498}
1499
1500const char * token_name(TokenId id) {
1501 switch (id) {
1502 case TokenIdAmpersand: return "&";
1503 case TokenIdArrow: return "->";
1504 case TokenIdBang: return "!";
1505 case TokenIdBarBar: return "||";
1506 case TokenIdBinOr: return "|";
1507 case TokenIdBinXor: return "^";
1508 case TokenIdBitAndEq: return "&=";
1509 case TokenIdBitOrEq: return "|=";
1510 case TokenIdBitShiftLeft: return "<<";
1511 case TokenIdBitShiftLeftEq: return "<<=";
1512 case TokenIdBitShiftLeftPipe: return "<<|";
1513 case TokenIdBitShiftLeftPipeEq: return "<<|=";
1514 case TokenIdBitShiftRight: return ">>";
1515 case TokenIdBitShiftRightEq: return ">>=";
1516 case TokenIdBitXorEq: return "^=";
1517 case TokenIdCharLiteral: return "CharLiteral";
1518 case TokenIdCmpEq: return "==";
1519 case TokenIdCmpGreaterOrEq: return ">=";
1520 case TokenIdCmpGreaterThan: return ">";
1521 case TokenIdCmpLessOrEq: return "<=";
1522 case TokenIdCmpLessThan: return "<";
1523 case TokenIdCmpNotEq: return "!=";
1524 case TokenIdColon: return ":";
1525 case TokenIdComma: return ",";
1526 case TokenIdDash: return "-";
1527 case TokenIdDivEq: return "/=";
1528 case TokenIdDocComment: return "DocComment";
1529 case TokenIdContainerDocComment: return "ContainerDocComment";
1530 case TokenIdDot: return ".";
1531 case TokenIdDotStar: return ".*";
1532 case TokenIdEllipsis2: return "..";
1533 case TokenIdEllipsis3: return "...";
1534 case TokenIdEof: return "EOF";
1535 case TokenIdEq: return "=";
1536 case TokenIdFatArrow: return "=>";
1537 case TokenIdFloatLiteral: return "FloatLiteral";
1538 case TokenIdIntLiteral: return "IntLiteral";
1539 case TokenIdKeywordAsync: return "async";
1540 case TokenIdKeywordAllowZero: return "allowzero";
1541 case TokenIdKeywordAwait: return "await";
1542 case TokenIdKeywordResume: return "resume";
1543 case TokenIdKeywordSuspend: return "suspend";
1544 case TokenIdKeywordAlign: return "align";
1545 case TokenIdKeywordAnd: return "and";
1546 case TokenIdKeywordAnyFrame: return "anyframe";
1547 case TokenIdKeywordAnyType: return "anytype";
1548 case TokenIdKeywordAsm: return "asm";
1549 case TokenIdKeywordBreak: return "break";
1550 case TokenIdKeywordCatch: return "catch";
1551 case TokenIdKeywordCallconv: return "callconv";
1552 case TokenIdKeywordCompTime: return "comptime";
1553 case TokenIdKeywordConst: return "const";
1554 case TokenIdKeywordContinue: return "continue";
1555 case TokenIdKeywordDefer: return "defer";
1556 case TokenIdKeywordElse: return "else";
1557 case TokenIdKeywordEnum: return "enum";
1558 case TokenIdKeywordErrdefer: return "errdefer";
1559 case TokenIdKeywordError: return "error";
1560 case TokenIdKeywordExport: return "export";
1561 case TokenIdKeywordExtern: return "extern";
1562 case TokenIdKeywordFn: return "fn";
1563 case TokenIdKeywordFor: return "for";
1564 case TokenIdKeywordIf: return "if";
1565 case TokenIdKeywordInline: return "inline";
1566 case TokenIdKeywordNoAlias: return "noalias";
1567 case TokenIdKeywordNoInline: return "noinline";
1568 case TokenIdKeywordNoSuspend: return "nosuspend";
1569 case TokenIdKeywordOpaque: return "opaque";
1570 case TokenIdKeywordOr: return "or";
1571 case TokenIdKeywordOrElse: return "orelse";
1572 case TokenIdKeywordPacked: return "packed";
1573 case TokenIdKeywordPub: return "pub";
1574 case TokenIdKeywordReturn: return "return";
1575 case TokenIdKeywordLinkSection: return "linksection";
1576 case TokenIdKeywordStruct: return "struct";
1577 case TokenIdKeywordSwitch: return "switch";
1578 case TokenIdKeywordTest: return "test";
1579 case TokenIdKeywordThreadLocal: return "threadlocal";
1580 case TokenIdKeywordTry: return "try";
1581 case TokenIdKeywordUnion: return "union";
1582 case TokenIdKeywordUnreachable: return "unreachable";
1583 case TokenIdKeywordUsingNamespace: return "usingnamespace";
1584 case TokenIdKeywordVar: return "var";
1585 case TokenIdKeywordVolatile: return "volatile";
1586 case TokenIdKeywordWhile: return "while";
1587 case TokenIdLBrace: return "{";
1588 case TokenIdLBracket: return "[";
1589 case TokenIdLParen: return "(";
1590 case TokenIdQuestion: return "?";
1591 case TokenIdMinusEq: return "-=";
1592 case TokenIdMinusPercent: return "-%";
1593 case TokenIdMinusPercentEq: return "-%=";
1594 case TokenIdMinusPipe: return "-|";
1595 case TokenIdMinusPipeEq: return "-|=";
1596 case TokenIdModEq: return "%=";
1597 case TokenIdPercent: return "%";
1598 case TokenIdPlus: return "+";
1599 case TokenIdPlusEq: return "+=";
1600 case TokenIdPlusPercent: return "+%";
1601 case TokenIdPlusPercentEq: return "+%=";
1602 case TokenIdPlusPipe: return "+|";
1603 case TokenIdPlusPipeEq: return "+|=";
1604 case TokenIdPlusPlus: return "++";
1605 case TokenIdRBrace: return "}";
1606 case TokenIdRBracket: return "]";
1607 case TokenIdRParen: return ")";
1608 case TokenIdSemicolon: return ";";
1609 case TokenIdSlash: return "/";
1610 case TokenIdStar: return "*";
1611 case TokenIdStarStar: return "**";
1612 case TokenIdStringLiteral: return "StringLiteral";
1613 case TokenIdMultilineStringLiteralLine: return "MultilineStringLiteralLine";
1614 case TokenIdIdentifier: return "Identifier";
1615 case TokenIdTilde: return "~";
1616 case TokenIdTimesEq: return "*=";
1617 case TokenIdTimesPercent: return "*%";
1618 case TokenIdTimesPercentEq: return "*%=";
1619 case TokenIdTimesPipe: return "*|";
1620 case TokenIdTimesPipeEq: return "*|=";
1621 case TokenIdBuiltin: return "Builtin";
1622 case TokenIdCount:
1623 zig_unreachable();
1624 }
1625 return "(invalid token)";
1626}
src/stage1/tokenizer.hpp deleted-161
...@@ -1,161 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_TOKENIZER_HPP
9#define ZIG_TOKENIZER_HPP
10
11#include "buffer.hpp"
12#include "bigint.hpp"
13#include "bigfloat.hpp"
14
15enum TokenId : uint8_t {
16 TokenIdAmpersand,
17 TokenIdArrow,
18 TokenIdBang,
19 TokenIdBarBar,
20 TokenIdBinOr,
21 TokenIdBinXor,
22 TokenIdBitAndEq,
23 TokenIdBitOrEq,
24 TokenIdBitShiftLeft,
25 TokenIdBitShiftLeftEq,
26 TokenIdBitShiftLeftPipe,
27 TokenIdBitShiftLeftPipeEq,
28 TokenIdBitShiftRight,
29 TokenIdBitShiftRightEq,
30 TokenIdBitXorEq,
31 TokenIdBuiltin,
32 TokenIdCharLiteral,
33 TokenIdCmpEq,
34 TokenIdCmpGreaterOrEq,
35 TokenIdCmpGreaterThan,
36 TokenIdCmpLessOrEq,
37 TokenIdCmpLessThan,
38 TokenIdCmpNotEq,
39 TokenIdColon,
40 TokenIdComma,
41 TokenIdDash,
42 TokenIdDivEq,
43 TokenIdDocComment,
44 TokenIdContainerDocComment,
45 TokenIdDot,
46 TokenIdDotStar,
47 TokenIdEllipsis2,
48 TokenIdEllipsis3,
49 TokenIdEof,
50 TokenIdEq,
51 TokenIdFatArrow,
52 TokenIdFloatLiteral,
53 TokenIdIntLiteral,
54 TokenIdKeywordAlign,
55 TokenIdKeywordAllowZero,
56 TokenIdKeywordAnd,
57 TokenIdKeywordAnyFrame,
58 TokenIdKeywordAnyType,
59 TokenIdKeywordAsm,
60 TokenIdKeywordAsync,
61 TokenIdKeywordAwait,
62 TokenIdKeywordBreak,
63 TokenIdKeywordCatch,
64 TokenIdKeywordCallconv,
65 TokenIdKeywordCompTime,
66 TokenIdKeywordConst,
67 TokenIdKeywordContinue,
68 TokenIdKeywordDefer,
69 TokenIdKeywordElse,
70 TokenIdKeywordEnum,
71 TokenIdKeywordErrdefer,
72 TokenIdKeywordError,
73 TokenIdKeywordExport,
74 TokenIdKeywordExtern,
75 TokenIdKeywordFn,
76 TokenIdKeywordFor,
77 TokenIdKeywordIf,
78 TokenIdKeywordInline,
79 TokenIdKeywordNoInline,
80 TokenIdKeywordLinkSection,
81 TokenIdKeywordNoAlias,
82 TokenIdKeywordNoSuspend,
83 TokenIdKeywordOpaque,
84 TokenIdKeywordOr,
85 TokenIdKeywordOrElse,
86 TokenIdKeywordPacked,
87 TokenIdKeywordPub,
88 TokenIdKeywordResume,
89 TokenIdKeywordReturn,
90 TokenIdKeywordStruct,
91 TokenIdKeywordSuspend,
92 TokenIdKeywordSwitch,
93 TokenIdKeywordTest,
94 TokenIdKeywordThreadLocal,
95 TokenIdKeywordTry,
96 TokenIdKeywordUnion,
97 TokenIdKeywordUnreachable,
98 TokenIdKeywordUsingNamespace,
99 TokenIdKeywordVar,
100 TokenIdKeywordVolatile,
101 TokenIdKeywordWhile,
102 TokenIdLBrace,
103 TokenIdLBracket,
104 TokenIdLParen,
105 TokenIdQuestion,
106 TokenIdMinusEq,
107 TokenIdMinusPercent,
108 TokenIdMinusPercentEq,
109 TokenIdMinusPipe,
110 TokenIdMinusPipeEq,
111 TokenIdModEq,
112 TokenIdPercent,
113 TokenIdPlus,
114 TokenIdPlusEq,
115 TokenIdPlusPercent,
116 TokenIdPlusPercentEq,
117 TokenIdPlusPipe,
118 TokenIdPlusPipeEq,
119 TokenIdPlusPlus,
120 TokenIdRBrace,
121 TokenIdRBracket,
122 TokenIdRParen,
123 TokenIdSemicolon,
124 TokenIdSlash,
125 TokenIdStar,
126 TokenIdStarStar,
127 TokenIdStringLiteral,
128 TokenIdMultilineStringLiteralLine,
129 TokenIdIdentifier,
130 TokenIdTilde,
131 TokenIdTimesEq,
132 TokenIdTimesPercent,
133 TokenIdTimesPercentEq,
134 TokenIdTimesPipe,
135 TokenIdTimesPipeEq,
136
137 TokenIdCount,
138};
139
140typedef uint32_t TokenIndex;
141
142struct TokenLoc {
143 uint32_t offset;
144 uint32_t line;
145 uint32_t column;
146};
147
148struct Tokenization {
149 ZigList<TokenId> ids;
150 ZigList<TokenLoc> locs;
151
152 // if an error occurred
153 Buf *err;
154 uint32_t err_byte_offset;
155};
156
157void tokenize(const char *source, Tokenization *out_tokenization);
158
159const char * token_name(TokenId id);
160
161#endif
src/stage1/util.cpp deleted-115
...@@ -1,115 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "util.hpp"
9#include "stage2.h"
10
11#include <stdio.h>
12#include <stdarg.h>
13
14void zig_panic(const char *format, ...) {
15 va_list ap;
16 va_start(ap, format);
17 vfprintf(stderr, format, ap);
18 fflush(stderr);
19 va_end(ap);
20 stage2_panic("", 0);
21 abort();
22}
23
24// Ported from std/mem.zig.
25bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte) {
26 for (size_t i = 0; i < self->split_bytes.len; i += 1) {
27 if (byte == self->split_bytes.ptr[i]) {
28 return true;
29 }
30 }
31 return false;
32}
33
34// Ported from std/mem.zig.
35Optional<Slice<uint8_t>> SplitIterator_next(SplitIterator *self) {
36 // move to beginning of token
37 while (self->index < self->buffer.len &&
38 SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
39 {
40 self->index += 1;
41 }
42 size_t start = self->index;
43 if (start == self->buffer.len) {
44 return {};
45 }
46
47 // move to end of token
48 while (self->index < self->buffer.len &&
49 !SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
50 {
51 self->index += 1;
52 }
53 size_t end = self->index;
54
55 return Optional<Slice<uint8_t>>::some(self->buffer.slice(start, end));
56}
57
58// Ported from std/mem.zig.
59// This one won't collapse multiple separators into one, so you could use it, for example,
60// to parse Comma Separated Value format.
61Optional<Slice<uint8_t>> SplitIterator_next_separate(SplitIterator *self) {
62 // move to beginning of token
63 if (self->index < self->buffer.len &&
64 SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
65 {
66 self->index += 1;
67 }
68 size_t start = self->index;
69 if (start == self->buffer.len) {
70 return {};
71 }
72
73 // move to end of token
74 while (self->index < self->buffer.len &&
75 !SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
76 {
77 self->index += 1;
78 }
79 size_t end = self->index;
80
81 return Optional<Slice<uint8_t>>::some(self->buffer.slice(start, end));
82}
83
84// Ported from std/mem.zig
85Slice<uint8_t> SplitIterator_rest(SplitIterator *self) {
86 // move to beginning of token
87 size_t index = self->index;
88 while (index < self->buffer.len && SplitIterator_isSplitByte(self, self->buffer.ptr[index])) {
89 index += 1;
90 }
91 return self->buffer.sliceFrom(index);
92}
93
94// Ported from std/mem.zig
95SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes) {
96 return SplitIterator{0, buffer, split_bytes};
97}
98
99void zig_pretty_print_bytes(FILE *f, double n) {
100 if (n > 1024.0 * 1024.0 * 1024.0) {
101 fprintf(f, "%.03f GiB", n / 1024.0 / 1024.0 / 1024.0);
102 return;
103 }
104 if (n > 1024.0 * 1024.0) {
105 fprintf(f, "%.03f MiB", n / 1024.0 / 1024.0);
106 return;
107 }
108 if (n > 1024.0) {
109 fprintf(f, "%.03f KiB", n / 1024.0);
110 return;
111 }
112 fprintf(f, "%.03f bytes", n );
113 return;
114}
115
src/stage1/util.hpp deleted-247
...@@ -1,247 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_UTIL_HPP
9#define ZIG_UTIL_HPP
10
11#include <stdlib.h>
12#include <stdint.h>
13#include <string.h>
14#include <ctype.h>
15
16#if defined(_MSC_VER)
17#include <intrin.h>
18#endif
19
20#define ZIG_Q(x) #x
21#define ZIG_QUOTE(x) ZIG_Q(x)
22
23#include "util_base.hpp"
24#include "heap.hpp"
25#include "mem.hpp"
26
27#if defined(_MSC_VER)
28static inline int clzll(unsigned long long mask) {
29 unsigned long lz;
30#if defined(_WIN64)
31 if (_BitScanReverse64(&lz, mask))
32 return static_cast<int>(63 - lz);
33 zig_unreachable();
34#else
35 if (_BitScanReverse(&lz, mask >> 32))
36 lz += 32;
37 else
38 _BitScanReverse(&lz, mask & 0xffffffff);
39 return 63 - lz;
40#endif
41}
42static inline int ctzll(unsigned long long mask) {
43 unsigned long result;
44#if defined(_WIN64)
45 if (_BitScanForward64(&result, mask))
46 return result;
47 zig_unreachable();
48#else
49 if (_BitScanForward(&result, mask & 0xffffffff))
50 return result;
51 if (_BitScanForward(&result, mask >> 32))
52 return 32 + result;
53 zig_unreachable();
54#endif
55}
56#else
57#define clzll(x) __builtin_clzll(x)
58#define ctzll(x) __builtin_ctzll(x)
59#endif
60
61template <typename T, size_t n>
62constexpr size_t array_length(const T (&)[n]) {
63 return n;
64}
65
66template <typename T>
67static inline T max(T a, T b) {
68 return (a >= b) ? a : b;
69}
70
71template <typename T>
72static inline T min(T a, T b) {
73 return (a <= b) ? a : b;
74}
75
76template<typename T>
77static inline T clamp(T min_value, T value, T max_value) {
78 return max(min(value, max_value), min_value);
79}
80
81static inline bool mem_eql_mem(const char *a_ptr, size_t a_len, const char *b_ptr, size_t b_len) {
82 if (a_len != b_len)
83 return false;
84 return memcmp(a_ptr, b_ptr, a_len) == 0;
85}
86static inline bool mem_eql_mem_ignore_case(const char *a_ptr, size_t a_len, const char *b_ptr, size_t b_len) {
87 if (a_len != b_len)
88 return false;
89 for (size_t i = 0; i < a_len; i += 1) {
90 if (tolower(a_ptr[i]) != tolower(b_ptr[i]))
91 return false;
92 }
93 return true;
94}
95
96static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) {
97 return mem_eql_mem(mem, mem_len, str, strlen(str));
98}
99
100static inline bool str_eql_str(const char *a, const char* b) {
101 return mem_eql_mem(a, strlen(a), b, strlen(b));
102}
103
104static inline bool str_eql_str_ignore_case(const char *a, const char* b) {
105 return mem_eql_mem_ignore_case(a, strlen(a), b, strlen(b));
106}
107
108static inline bool is_power_of_2(uint64_t x) {
109 return x != 0 && ((x & (~x + 1)) == x);
110}
111
112static inline bool mem_ends_with_mem(const char *mem, size_t mem_len, const char *end, size_t end_len) {
113 if (mem_len < end_len) return false;
114 return memcmp(mem + mem_len - end_len, end, end_len) == 0;
115}
116
117static inline bool mem_ends_with_str(const char *mem, size_t mem_len, const char *str) {
118 return mem_ends_with_mem(mem, mem_len, str, strlen(str));
119}
120
121static inline uint64_t round_to_next_power_of_2(uint64_t x) {
122 --x;
123 x |= x >> 1;
124 x |= x >> 2;
125 x |= x >> 4;
126 x |= x >> 8;
127 x |= x >> 16;
128 x |= x >> 32;
129 return x + 1;
130}
131
132static inline uint8_t log2_u64(uint64_t x) {
133 return (63 - clzll(x));
134}
135
136void zig_pretty_print_bytes(FILE *f, double n);
137
138template<typename T>
139struct Optional {
140 T value;
141 bool is_some;
142
143 static inline Optional<T> some(T x) {
144 return {x, true};
145 }
146
147 static inline Optional<T> none() {
148 return {{}, false};
149 }
150
151 inline bool unwrap(T *res) {
152 *res = value;
153 return is_some;
154 }
155};
156
157template<typename T>
158struct Slice {
159 T *ptr;
160 size_t len;
161
162 inline T &at(size_t i) {
163 assert(i < len);
164 return ptr[i];
165 }
166
167 inline Slice<T> slice(size_t start, size_t end) {
168 assert(end <= len);
169 assert(end >= start);
170 return {
171 ptr + start,
172 end - start,
173 };
174 }
175
176 inline Slice<T> sliceFrom(size_t start) {
177 assert(start <= len);
178 return {
179 ptr + start,
180 len - start,
181 };
182 }
183
184 static inline Slice<T> alloc(size_t n) {
185 return {heap::c_allocator.allocate_nonzero<T>(n), n};
186 }
187};
188
189template<typename T, size_t n>
190struct Array {
191 static const size_t len = n;
192 T items[n];
193
194 inline Slice<T> slice() {
195 return {
196 &items[0],
197 len,
198 };
199 }
200};
201
202static inline Slice<uint8_t> str(const char *literal) {
203 return {(uint8_t*)(literal), strlen(literal)};
204}
205
206// Ported from std/mem.zig
207template<typename T>
208static inline bool memEql(Slice<T> a, Slice<T> b) {
209 if (a.len != b.len)
210 return false;
211 for (size_t i = 0; i < a.len; i += 1) {
212 if (a.ptr[i] != b.ptr[i])
213 return false;
214 }
215 return true;
216}
217
218// Ported from std/mem.zig
219template<typename T>
220static inline bool memStartsWith(Slice<T> haystack, Slice<T> needle) {
221 if (needle.len > haystack.len)
222 return false;
223 return memEql(haystack.slice(0, needle.len), needle);
224}
225
226// Ported from std/mem.zig
227template<typename T>
228static inline void memCopy(Slice<T> dest, Slice<T> src) {
229 assert(dest.len >= src.len);
230 memcpy(dest.ptr, src.ptr, src.len * sizeof(T));
231}
232
233// Ported from std/mem.zig.
234// Coordinate struct fields with memSplit function
235struct SplitIterator {
236 size_t index;
237 Slice<uint8_t> buffer;
238 Slice<uint8_t> split_bytes;
239};
240
241bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte);
242Optional< Slice<uint8_t> > SplitIterator_next(SplitIterator *self);
243Optional< Slice<uint8_t> > SplitIterator_next_separate(SplitIterator *self);
244Slice<uint8_t> SplitIterator_rest(SplitIterator *self);
245SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes);
246
247#endif
src/stage1/util_base.hpp deleted-77
...@@ -1,77 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_UTIL_BASE_HPP
9#define ZIG_UTIL_BASE_HPP
10
11#include <assert.h>
12
13#if defined(_MSC_VER)
14
15#define ATTRIBUTE_COLD __declspec(noinline)
16#define ATTRIBUTE_PRINTF(a, b)
17#define ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict)
18#define ATTRIBUTE_NORETURN __declspec(noreturn)
19#define ATTRIBUTE_MUST_USE
20
21#define BREAKPOINT __debugbreak()
22
23#else
24
25#define ATTRIBUTE_COLD __attribute__((cold))
26#define ATTRIBUTE_PRINTF(a, b) __attribute__((format(printf, a, b)))
27#define ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__))
28#define ATTRIBUTE_NORETURN __attribute__((noreturn))
29#define ATTRIBUTE_MUST_USE __attribute__((warn_unused_result))
30
31#if defined(__MINGW32__) || defined(__MINGW64__)
32#define BREAKPOINT __debugbreak()
33#elif defined(__i386__) || defined(__x86_64__)
34#define BREAKPOINT __asm__ volatile("int $0x03");
35#elif defined(__clang__)
36#define BREAKPOINT __builtin_debugtrap()
37#elif defined(__GNUC__)
38#define BREAKPOINT __builtin_trap()
39#else
40#include <signal.h>
41#define BREAKPOINT raise(SIGTRAP)
42#endif
43
44#endif
45
46ATTRIBUTE_COLD
47ATTRIBUTE_NORETURN
48ATTRIBUTE_PRINTF(1, 2)
49void zig_panic(const char *format, ...);
50
51static inline void zig_assert(bool ok, const char *file, int line, const char *func) {
52 if (!ok) {
53 zig_panic("Assertion failed at %s:%d in %s. This is a bug in the Zig compiler.", file, line, func);
54 }
55}
56
57#ifdef _WIN32
58#define __func__ __FUNCTION__
59#endif
60
61#define zig_unreachable() zig_panic("Unreachable at %s:%d in %s. This is a bug in the Zig compiler.", __FILE__, __LINE__, __func__)
62
63// Assertions in stage1 are always on, and they call zig @panic.
64#undef assert
65#define assert(ok) zig_assert(ok, __FILE__, __LINE__, __func__)
66
67#if defined(_MSC_VER)
68#define ZIG_FALLTHROUGH
69#elif defined(__clang__)
70#define ZIG_FALLTHROUGH [[clang::fallthrough]]
71#elif defined(__GNUC__) && __GNUC__ >= 7
72#define ZIG_FALLTHROUGH __attribute__((fallthrough))
73#else
74#define ZIG_FALLTHROUGH
75#endif
76
77#endif
src/stage1/zig0.cpp deleted-578
...@@ -1,578 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8// This file is the entry point for zig0, which is *only* used to build
9// stage2, the self-hosted compiler, into an object file, which is then
10// linked by the same build system (cmake) that linked this binary.
11
12#include "stage1.h"
13#include "heap.hpp"
14#include "stage2.h"
15#include "target.hpp"
16#include "error.hpp"
17#include "util.hpp"
18#include "buffer.hpp"
19#include "os.hpp"
20
21#ifndef ZIG_VERSION_STRING
22#include "config.h"
23#endif
24
25#include <stdio.h>
26#include <string.h>
27
28static int print_error_usage(const char *arg0) {
29 fprintf(stderr, "See `%s --help` for detailed usage information\n", arg0);
30 return EXIT_FAILURE;
31}
32
33static int print_full_usage(const char *arg0, FILE *file, int return_code) {
34 fprintf(file,
35 "Usage: %s [options] builds an object file\n"
36 "\n"
37 "Options:\n"
38 " --color [auto|off|on] enable or disable colored error messages\n"
39 " --name [name] override output name\n"
40 " -femit-bin=[path] Output machine code\n"
41 " -fcompiler-rt Always include compiler-rt symbols in output\n"
42 " --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
43 " --pkg-end pop current pkg\n"
44 " -ODebug build with optimizations off and safety on\n"
45 " -OReleaseFast build with optimizations on and safety off\n"
46 " -OReleaseSafe build with optimizations on and safety on\n"
47 " -OReleaseSmall build with size optimizations on and safety off\n"
48 " -fsingle-threaded source may assume it is only used single-threaded\n"
49 " -dynamic create a shared library (.so; .dll; .dylib)\n"
50 " --strip exclude debug symbols\n"
51 " -target [name] <arch>-<os>-<abi> see the targets command\n"
52 " -mcpu [cpu] specify target CPU and feature set\n"
53 " --verbose-ir enable compiler debug output for Zig IR\n"
54 " --verbose-llvm-ir enable compiler debug output for LLVM IR\n"
55 " --verbose-cimport enable compiler debug output for C imports\n"
56 " --verbose-llvm-cpu-features enable compiler debug output for LLVM CPU features\n"
57 "\n"
58 , arg0);
59 return return_code;
60}
61
62static Os get_zig_os_type(ZigLLVM_OSType os_type) {
63 switch (os_type) {
64 case ZigLLVM_UnknownOS:
65 return OsFreestanding;
66 case ZigLLVM_Ananas:
67 return OsAnanas;
68 case ZigLLVM_CloudABI:
69 return OsCloudABI;
70 case ZigLLVM_DragonFly:
71 return OsDragonFly;
72 case ZigLLVM_FreeBSD:
73 return OsFreeBSD;
74 case ZigLLVM_Fuchsia:
75 return OsFuchsia;
76 case ZigLLVM_IOS:
77 return OsIOS;
78 case ZigLLVM_KFreeBSD:
79 return OsKFreeBSD;
80 case ZigLLVM_Linux:
81 return OsLinux;
82 case ZigLLVM_Lv2:
83 return OsLv2;
84 case ZigLLVM_Darwin:
85 case ZigLLVM_MacOSX:
86 return OsMacOSX;
87 case ZigLLVM_NetBSD:
88 return OsNetBSD;
89 case ZigLLVM_OpenBSD:
90 return OsOpenBSD;
91 case ZigLLVM_Solaris:
92 return OsSolaris;
93 case ZigLLVM_Win32:
94 return OsWindows;
95 case ZigLLVM_ZOS:
96 return OsZOS;
97 case ZigLLVM_Haiku:
98 return OsHaiku;
99 case ZigLLVM_Minix:
100 return OsMinix;
101 case ZigLLVM_RTEMS:
102 return OsRTEMS;
103 case ZigLLVM_NaCl:
104 return OsNaCl;
105 case ZigLLVM_AIX:
106 return OsAIX;
107 case ZigLLVM_CUDA:
108 return OsCUDA;
109 case ZigLLVM_NVCL:
110 return OsNVCL;
111 case ZigLLVM_AMDHSA:
112 return OsAMDHSA;
113 case ZigLLVM_PS4:
114 return OsPS4;
115 case ZigLLVM_PS5:
116 return OsPS5;
117 case ZigLLVM_ELFIAMCU:
118 return OsELFIAMCU;
119 case ZigLLVM_TvOS:
120 return OsTvOS;
121 case ZigLLVM_WatchOS:
122 return OsWatchOS;
123 case ZigLLVM_Mesa3D:
124 return OsMesa3D;
125 case ZigLLVM_Contiki:
126 return OsContiki;
127 case ZigLLVM_AMDPAL:
128 return OsAMDPAL;
129 case ZigLLVM_HermitCore:
130 return OsHermitCore;
131 case ZigLLVM_Hurd:
132 return OsHurd;
133 case ZigLLVM_WASI:
134 return OsWASI;
135 case ZigLLVM_Emscripten:
136 return OsEmscripten;
137 case ZigLLVM_DriverKit:
138 return OsDriverKit;
139 case ZigLLVM_ShaderModel:
140 return OsShaderModel;
141 }
142 zig_unreachable();
143}
144
145static void get_native_target(ZigTarget *target) {
146 // first zero initialize
147 *target = {};
148
149 ZigLLVM_OSType os_type;
150 ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os
151 ZigLLVM_VendorType trash;
152 ZigLLVMGetNativeTarget(
153 &target->arch,
154 &trash,
155 &os_type,
156 &target->abi,
157 &oformat);
158 target->os = get_zig_os_type(os_type);
159 target->is_native_os = true;
160 target->is_native_cpu = true;
161 if (target->abi == ZigLLVM_UnknownEnvironment) {
162 target->abi = target_default_abi(target->arch, target->os);
163 }
164}
165
166static const char* get_baseline_llvm_cpu_name(ZigLLVM_ArchType arch) {
167 return "";
168}
169
170static const char* get_baseline_llvm_cpu_features(ZigLLVM_ArchType arch) {
171 switch (arch) {
172 case ZigLLVM_riscv64: return "+a,+c,+d,+m";
173 default: return "";
174 }
175}
176
177static Error target_parse_triple(struct ZigTarget *target, const char *zig_triple, const char *mcpu,
178 const char *dynamic_linker)
179{
180 Error err;
181
182 if (zig_triple != nullptr && strcmp(zig_triple, "native") == 0) {
183 zig_triple = nullptr;
184 }
185
186 if (zig_triple == nullptr) {
187 get_native_target(target);
188
189 if (mcpu == nullptr || strcmp(mcpu, "native") == 0) {
190 target->llvm_cpu_name = ZigLLVMGetHostCPUName();
191 target->llvm_cpu_features = ZigLLVMGetNativeFeatures();
192 } else if (strcmp(mcpu, "baseline") == 0) {
193 target->is_native_os = false;
194 target->is_native_cpu = false;
195 target->llvm_cpu_name = get_baseline_llvm_cpu_name(target->arch);
196 target->llvm_cpu_features = get_baseline_llvm_cpu_features(target->arch);
197 } else {
198 const char *msg = "stage0 can't handle CPU/features in the target";
199 stage2_panic(msg, strlen(msg));
200 }
201 } else {
202 // first initialize all to zero
203 *target = {};
204
205 SplitIterator it = memSplit(str(zig_triple), str("-"));
206
207 Optional<Slice<uint8_t>> opt_archsub = SplitIterator_next(&it);
208 Optional<Slice<uint8_t>> opt_os = SplitIterator_next(&it);
209 Optional<Slice<uint8_t>> opt_abi = SplitIterator_next(&it);
210
211 if (!opt_archsub.is_some)
212 return ErrorMissingArchitecture;
213
214 if ((err = target_parse_arch(&target->arch, (char*)opt_archsub.value.ptr, opt_archsub.value.len))) {
215 return err;
216 }
217
218 if (!opt_os.is_some)
219 return ErrorMissingOperatingSystem;
220
221 if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) {
222 return err;
223 }
224
225 if (opt_abi.is_some) {
226 if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) {
227 return err;
228 }
229 } else {
230 target->abi = target_default_abi(target->arch, target->os);
231 }
232
233 if (mcpu != nullptr && strcmp(mcpu, "baseline") != 0) {
234 const char *msg = "stage0 can't handle CPU/features in the target";
235 stage2_panic(msg, strlen(msg));
236 }
237
238 target->llvm_cpu_name = get_baseline_llvm_cpu_name(target->arch);
239 target->llvm_cpu_features = get_baseline_llvm_cpu_features(target->arch);
240 }
241
242 return ErrorNone;
243}
244
245
246static bool str_starts_with(const char *s1, const char *s2) {
247 size_t s2_len = strlen(s2);
248 if (strlen(s1) < s2_len) {
249 return false;
250 }
251 return memcmp(s1, s2, s2_len) == 0;
252}
253
254int main_exit(Stage2ProgressNode *root_progress_node, int exit_code) {
255 if (root_progress_node != nullptr) {
256 stage2_progress_end(root_progress_node);
257 }
258 return exit_code;
259}
260
261int main(int argc, char **argv) {
262 zig_stage1_os_init();
263
264 char *arg0 = argv[0];
265 Error err;
266
267 const char *in_file = nullptr;
268 const char *emit_bin_path = nullptr;
269 bool strip = false;
270 const char *out_name = nullptr;
271 bool verbose_ir = false;
272 bool verbose_llvm_ir = false;
273 bool verbose_cimport = false;
274 bool verbose_llvm_cpu_features = false;
275 ErrColor color = ErrColorAuto;
276 const char *dynamic_linker = nullptr;
277 bool link_libc = false;
278 bool link_libcpp = false;
279 const char *target_string = nullptr;
280 ZigStage1Pkg *cur_pkg = heap::c_allocator.create<ZigStage1Pkg>();
281 BuildMode optimize_mode = BuildModeDebug;
282 TargetSubsystem subsystem = TargetSubsystemAuto;
283 const char *override_lib_dir = nullptr;
284 const char *mcpu = nullptr;
285 bool single_threaded = false;
286 bool is_test_build = false;
287 bool include_compiler_rt = false;
288
289 for (int i = 1; i < argc; i += 1) {
290 char *arg = argv[i];
291
292 if (arg[0] == '-') {
293 if (strcmp(arg, "--") == 0) {
294 fprintf(stderr, "Unexpected end-of-parameter mark: %s\n", arg);
295 } else if (strcmp(arg, "--test") == 0) {
296 is_test_build = true;
297 } else if (strcmp(arg, "-ODebug") == 0) {
298 optimize_mode = BuildModeDebug;
299 } else if (strcmp(arg, "-OReleaseFast") == 0) {
300 optimize_mode = BuildModeFastRelease;
301 } else if (strcmp(arg, "-OReleaseSafe") == 0) {
302 optimize_mode = BuildModeSafeRelease;
303 } else if (strcmp(arg, "-OReleaseSmall") == 0) {
304 optimize_mode = BuildModeSmallRelease;
305 } else if (strcmp(arg, "-fsingle-threaded") == 0) {
306 single_threaded = true;
307 } else if (strcmp(arg, "--help") == 0) {
308 return print_full_usage(arg0, stdout, EXIT_SUCCESS);
309 } else if (strcmp(arg, "--strip") == 0) {
310 strip = true;
311 } else if (strcmp(arg, "--verbose-ir") == 0) {
312 verbose_ir = true;
313 } else if (strcmp(arg, "--verbose-llvm-ir") == 0) {
314 verbose_llvm_ir = true;
315 } else if (strcmp(arg, "--verbose-cimport") == 0) {
316 verbose_cimport = true;
317 } else if (strcmp(arg, "--verbose-llvm-cpu-features") == 0) {
318 verbose_llvm_cpu_features = true;
319 } else if (arg[1] == 'l' && arg[2] != 0) {
320 // alias for --library
321 const char *l = &arg[2];
322 if (strcmp(l, "c") == 0) {
323 link_libc = true;
324 } else if (strcmp(l, "c++") == 0 || strcmp(l, "stdc++") == 0) {
325 link_libcpp = true;
326 }
327 } else if (strcmp(arg, "--pkg-begin") == 0) {
328 if (i + 2 >= argc) {
329 fprintf(stderr, "Expected 2 arguments after --pkg-begin\n");
330 return print_error_usage(arg0);
331 }
332 ZigStage1Pkg *new_cur_pkg = heap::c_allocator.create<ZigStage1Pkg>();
333 i += 1;
334 new_cur_pkg->name_ptr = argv[i];
335 new_cur_pkg->name_len = strlen(argv[i]);
336 i += 1;
337 new_cur_pkg->path_ptr = argv[i];
338 new_cur_pkg->path_len = strlen(argv[i]);
339 new_cur_pkg->parent = cur_pkg;
340 cur_pkg->children_ptr = heap::c_allocator.reallocate<ZigStage1Pkg *>(cur_pkg->children_ptr,
341 cur_pkg->children_len, cur_pkg->children_len + 1);
342 cur_pkg->children_ptr[cur_pkg->children_len] = new_cur_pkg;
343 cur_pkg->children_len += 1;
344
345 cur_pkg = new_cur_pkg;
346 } else if (strcmp(arg, "--pkg-end") == 0) {
347 if (cur_pkg->parent == nullptr) {
348 fprintf(stderr, "Encountered --pkg-end with no matching --pkg-begin\n");
349 return EXIT_FAILURE;
350 }
351 cur_pkg = cur_pkg->parent;
352 } else if (str_starts_with(arg, "-mcpu=")) {
353 mcpu = arg + strlen("-mcpu=");
354 } else if (str_starts_with(arg, "-femit-bin=")) {
355 emit_bin_path = arg + strlen("-femit-bin=");
356 } else if (strcmp(arg, "-fcompiler-rt") == 0) {
357 include_compiler_rt = true;
358 } else if (i + 1 >= argc) {
359 fprintf(stderr, "Expected another argument after %s\n", arg);
360 return print_error_usage(arg0);
361 } else {
362 i += 1;
363 if (strcmp(arg, "--color") == 0) {
364 if (strcmp(argv[i], "auto") == 0) {
365 color = ErrColorAuto;
366 } else if (strcmp(argv[i], "on") == 0) {
367 color = ErrColorOn;
368 } else if (strcmp(argv[i], "off") == 0) {
369 color = ErrColorOff;
370 } else {
371 fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n");
372 return print_error_usage(arg0);
373 }
374 } else if (strcmp(arg, "--name") == 0) {
375 out_name = argv[i];
376 } else if (strcmp(arg, "--dynamic-linker") == 0) {
377 dynamic_linker = argv[i];
378 } else if (strcmp(arg, "--zig-lib-dir") == 0) {
379 override_lib_dir = argv[i];
380 } else if (strcmp(arg, "--library") == 0 || strcmp(arg, "-l") == 0) {
381 if (strcmp(argv[i], "c") == 0) {
382 link_libc = true;
383 } else if (strcmp(argv[i], "c++") == 0 || strcmp(argv[i], "stdc++") == 0) {
384 link_libcpp = true;
385 }
386 } else if (strcmp(arg, "-target") == 0) {
387 target_string = argv[i];
388 } else if (strcmp(arg, "--subsystem") == 0) {
389 if (strcmp(argv[i], "console") == 0) {
390 subsystem = TargetSubsystemConsole;
391 } else if (strcmp(argv[i], "windows") == 0) {
392 subsystem = TargetSubsystemWindows;
393 } else if (strcmp(argv[i], "posix") == 0) {
394 subsystem = TargetSubsystemPosix;
395 } else if (strcmp(argv[i], "native") == 0) {
396 subsystem = TargetSubsystemNative;
397 } else if (strcmp(argv[i], "efi_application") == 0) {
398 subsystem = TargetSubsystemEfiApplication;
399 } else if (strcmp(argv[i], "efi_boot_service_driver") == 0) {
400 subsystem = TargetSubsystemEfiBootServiceDriver;
401 } else if (strcmp(argv[i], "efi_rom") == 0) {
402 subsystem = TargetSubsystemEfiRom;
403 } else if (strcmp(argv[i], "efi_runtime_driver") == 0) {
404 subsystem = TargetSubsystemEfiRuntimeDriver;
405 } else {
406 fprintf(stderr, "invalid: --subsystem %s\n"
407 "Options are:\n"
408 " console\n"
409 " windows\n"
410 " posix\n"
411 " native\n"
412 " efi_application\n"
413 " efi_boot_service_driver\n"
414 " efi_rom\n"
415 " efi_runtime_driver\n"
416 , argv[i]);
417 return EXIT_FAILURE;
418 }
419 } else if (strcmp(arg, "-mcpu") == 0) {
420 mcpu = argv[i];
421 } else {
422 fprintf(stderr, "Invalid argument: %s\n", arg);
423 return print_error_usage(arg0);
424 }
425 }
426 } else if (!in_file) {
427 in_file = arg;
428 } else {
429 fprintf(stderr, "Unexpected extra parameter: %s\n", arg);
430 return print_error_usage(arg0);
431 }
432 }
433
434 if (cur_pkg->parent != nullptr) {
435 fprintf(stderr, "Unmatched --pkg-begin\n");
436 return EXIT_FAILURE;
437 }
438
439 Stage2Progress *progress = stage2_progress_create();
440 Stage2ProgressNode *root_progress_node = stage2_progress_start_root(progress, "", 0, 0);
441 if (color == ErrColorOff) stage2_progress_disable_tty(progress);
442
443 ZigTarget target;
444 if ((err = target_parse_triple(&target, target_string, mcpu, dynamic_linker))) {
445 fprintf(stderr, "invalid target: %s\n", err_str(err));
446 return print_error_usage(arg0);
447 }
448
449 if (in_file == nullptr) {
450 fprintf(stderr, "missing zig file\n");
451 return print_error_usage(arg0);
452 }
453
454 if (out_name == nullptr) {
455 fprintf(stderr, "missing --name\n");
456 return print_error_usage(arg0);
457 }
458
459 if (override_lib_dir == nullptr) {
460 fprintf(stderr, "missing --zig-lib-dir\n");
461 return print_error_usage(arg0);
462 }
463
464 if (emit_bin_path == nullptr) {
465 fprintf(stderr, "missing -femit-bin=\n");
466 return print_error_usage(arg0);
467 }
468
469 ZigStage1 *stage1 = zig_stage1_create(optimize_mode,
470 nullptr, 0,
471 in_file, strlen(in_file),
472 override_lib_dir, strlen(override_lib_dir),
473 &target, is_test_build);
474
475 stage1->main_progress_node = root_progress_node;
476 stage1->root_name_ptr = out_name;
477 stage1->root_name_len = strlen(out_name);
478 stage1->strip = strip;
479 stage1->verbose_ir = verbose_ir;
480 stage1->verbose_llvm_ir = verbose_llvm_ir;
481 stage1->verbose_cimport = verbose_cimport;
482 stage1->verbose_llvm_cpu_features = verbose_llvm_cpu_features;
483 stage1->emit_o_ptr = emit_bin_path;
484 stage1->emit_o_len = strlen(emit_bin_path);
485 stage1->main_pkg = cur_pkg;
486 stage1->err_color = color;
487 stage1->link_libc = link_libc;
488 stage1->link_libcpp = link_libcpp;
489 stage1->subsystem = subsystem;
490 stage1->pic = true;
491 stage1->is_single_threaded = single_threaded;
492 stage1->include_compiler_rt = include_compiler_rt;
493
494 zig_stage1_build_object(stage1);
495
496 zig_stage1_destroy(stage1);
497
498 return main_exit(root_progress_node, EXIT_SUCCESS);
499}
500
501void stage2_panic(const char *ptr, size_t len) {
502 fwrite(ptr, 1, len, stderr);
503 fprintf(stderr, "\n");
504 fflush(stderr);
505 abort();
506}
507
508struct Stage2Progress {
509 int trash;
510};
511
512struct Stage2ProgressNode {
513 int trash;
514};
515
516Stage2Progress *stage2_progress_create(void) {
517 return nullptr;
518}
519
520void stage2_progress_destroy(Stage2Progress *progress) {}
521
522Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
523 const char *name_ptr, size_t name_len, size_t estimated_total_items)
524{
525 return nullptr;
526}
527Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
528 const char *name_ptr, size_t name_len, size_t estimated_total_items)
529{
530 return nullptr;
531}
532void stage2_progress_end(Stage2ProgressNode *node) {}
533void stage2_progress_complete_one(Stage2ProgressNode *node) {}
534void stage2_progress_disable_tty(Stage2Progress *progress) {}
535void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){}
536
537const char *stage2_fetch_file(struct ZigStage1 *stage1, const char *path_ptr, size_t path_len,
538 size_t *result_len)
539{
540 Error err;
541 Buf contents_buf = BUF_INIT;
542 Buf path_buf = BUF_INIT;
543
544 buf_init_from_mem(&path_buf, path_ptr, path_len);
545 if ((err = os_fetch_file_path(&path_buf, &contents_buf))) {
546 return nullptr;
547 }
548 *result_len = buf_len(&contents_buf);
549 return buf_ptr(&contents_buf);
550}
551
552Error stage2_cimport(struct ZigStage1 *stage1, const char *c_src_ptr, size_t c_src_len,
553 const char **out_zig_path_ptr, size_t *out_zig_path_len,
554 struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len)
555{
556 const char *msg = "stage0 called stage2_cimport";
557 stage2_panic(msg, strlen(msg));
558}
559
560const char *stage2_add_link_lib(struct ZigStage1 *stage1,
561 const char *lib_name_ptr, size_t lib_name_len,
562 const char *symbol_name_ptr, size_t symbol_name_len)
563{
564 return nullptr;
565}
566
567const char *stage2_version_string(void) {
568 return ZIG_VERSION_STRING;
569}
570
571struct Stage2SemVer stage2_version(void) {
572 return {ZIG_VERSION_MAJOR, ZIG_VERSION_MINOR, ZIG_VERSION_PATCH};
573}
574
575Error stage2_append_symbol(struct ZigStage1 *stage1, const char *name_ptr, size_t name_len)
576{
577 return ErrorNone;
578}
src/stage1/zigendian.h deleted-34
...@@ -1,34 +0,0 @@
1#ifndef ZIG_ENDIAN_H
2#define ZIG_ENDIAN_H
3
4// Every OSes seem to define endianness macros in different files.
5#if defined(__APPLE__)
6 #include <machine/endian.h>
7 #define ZIG_BIG_ENDIAN BIG_ENDIAN
8 #define ZIG_LITTLE_ENDIAN LITTLE_ENDIAN
9 #define ZIG_BYTE_ORDER BYTE_ORDER
10#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
11 #include <sys/endian.h>
12 #define ZIG_BIG_ENDIAN _BIG_ENDIAN
13 #define ZIG_LITTLE_ENDIAN _LITTLE_ENDIAN
14 #define ZIG_BYTE_ORDER _BYTE_ORDER
15#elif defined(_WIN32) || defined(_WIN64)
16 // Assume that Windows installations are always little endian.
17 #define ZIG_LITTLE_ENDIAN 1
18 #define ZIG_BYTE_ORDER ZIG_LITTLE_ENDIAN
19#else // Linux
20 #include <endian.h>
21 #define ZIG_BIG_ENDIAN __BIG_ENDIAN
22 #define ZIG_LITTLE_ENDIAN __LITTLE_ENDIAN
23 #define ZIG_BYTE_ORDER __BYTE_ORDER
24#endif
25
26#if defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
27 const bool native_is_big_endian = false;
28#elif defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN
29 const bool native_is_big_endian = true;
30#else
31 #error Unsupported endian
32#endif
33
34#endif // ZIG_ENDIAN_H